Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAtsushi Eno <atsushieno@gmail.com>2004-10-22 22:36:23 +0400
committerAtsushi Eno <atsushieno@gmail.com>2004-10-22 22:36:23 +0400
commitdda2afcff17e525e74f9294622ffcbb652589d22 (patch)
tree15a797880dcb70f81591b119806d59f757848505 /mcs/class/Mono.Xml.Ext
parent05009bb9af0404c3efb0e980850bccec466da6c1 (diff)
2004-10-22 Atsushi Enomoto <atsushi@ximian.com>
SequenceType.cs, XPath2Expression.cs, XPathSequence.cs, XQueryASTCompiler.cs, XQueryArithmeticOperator.cs, XQueryCliFunction.cs, XQueryCommandImpl.cs, XQueryComparisonOperator.cs, XQueryCompileContext.cs, XQueryCompileOptions.cs, XQueryContext.cs, XQueryConvert.cs, XQueryDefaultFunctionCall.cs, (not in use), XQueryExpression.cs, XQueryFunction.cs, XQueryFunctionCliImpl.cs, XQueryFunctionContextAttribute.cs, XQueryFunctionTable.cs, XQueryModuleProlog.cs, XQueryStaticContext.cs, XQueryTokenizer.cs, XmlQueryCompileException.cs, XmlQueryException.cs, XQueryParser.jay, skelton-2.0.cs: Initial Checkin (it is not compiled as yet). svn path=/trunk/mcs/; revision=35257
Diffstat (limited to 'mcs/class/Mono.Xml.Ext')
-rwxr-xr-xmcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/ChangeLog28
-rwxr-xr-xmcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/SequenceType.cs728
-rwxr-xr-xmcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XPath2Expression.cs2439
-rwxr-xr-xmcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XPathSequence.cs1779
-rwxr-xr-xmcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XQueryASTCompiler.cs265
-rwxr-xr-xmcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XQueryArithmeticOperator.cs368
-rwxr-xr-xmcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XQueryCliFunction.cs210
-rwxr-xr-xmcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XQueryCommandImpl.cs100
-rwxr-xr-xmcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XQueryComparisonOperator.cs235
-rwxr-xr-xmcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XQueryCompileContext.cs93
-rwxr-xr-xmcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XQueryCompileOptions.cs101
-rwxr-xr-xmcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XQueryContext.cs318
-rwxr-xr-xmcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XQueryConvert.cs1021
-rwxr-xr-xmcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XQueryDefaultFunctionCall.cs387
-rwxr-xr-xmcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XQueryExpression.cs579
-rwxr-xr-xmcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XQueryFunction.cs322
-rwxr-xr-xmcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XQueryFunctionCliImpl.cs1135
-rwxr-xr-xmcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XQueryFunctionContextAttribute.cs45
-rwxr-xr-xmcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XQueryFunctionTable.cs66
-rwxr-xr-xmcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XQueryModuleProlog.cs529
-rwxr-xr-xmcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XQueryParser.jay2535
-rwxr-xr-xmcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XQueryStaticContext.cs231
-rwxr-xr-xmcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XQueryTokenizer.cs1285
-rwxr-xr-xmcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XmlQueryCompileException.cs74
-rwxr-xr-xmcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XmlQueryException.cs112
-rwxr-xr-xmcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/skeleton-2.0.cs364
26 files changed, 15349 insertions, 0 deletions
diff --git a/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/ChangeLog b/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/ChangeLog
new file mode 100755
index 00000000000..fe9cf44b453
--- /dev/null
+++ b/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/ChangeLog
@@ -0,0 +1,28 @@
+2004-10-22 Atsushi Enomoto <atsushi@ximian.com>
+
+ SequenceType.cs,
+ XPath2Expression.cs,
+ XPathSequence.cs,
+ XQueryASTCompiler.cs,
+ XQueryArithmeticOperator.cs,
+ XQueryCliFunction.cs,
+ XQueryCommandImpl.cs,
+ XQueryComparisonOperator.cs,
+ XQueryCompileContext.cs,
+ XQueryCompileOptions.cs,
+ XQueryContext.cs,
+ XQueryConvert.cs,
+ XQueryDefaultFunctionCall.cs, (not in use),
+ XQueryExpression.cs,
+ XQueryFunction.cs,
+ XQueryFunctionCliImpl.cs,
+ XQueryFunctionContextAttribute.cs,
+ XQueryFunctionTable.cs,
+ XQueryModuleProlog.cs,
+ XQueryStaticContext.cs,
+ XQueryTokenizer.cs,
+ XmlQueryCompileException.cs,
+ XmlQueryException.cs,
+ XQueryParser.jay,
+ skelton-2.0.cs: Initial Checkin (it is not compiled as yet).
+
diff --git a/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/SequenceType.cs b/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/SequenceType.cs
new file mode 100755
index 00000000000..dadaeb8b8f0
--- /dev/null
+++ b/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/SequenceType.cs
@@ -0,0 +1,728 @@
+//
+// SequenceType.cs - represents XPath 2.0 item type
+//
+// Author:
+// Atsushi Enomoto <atsushi@ximian.com>
+//
+//
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+#if NET_2_0
+using System;
+using System.Collections;
+using System.Globalization;
+using System.Xml;
+using System.Xml.Schema;
+using System.Xml.Query;
+using System.Xml.XPath;
+using Mono.Xml;
+
+namespace Mono.Xml.XPath2
+{
+ public class SequenceType
+ {
+ static SequenceType singleItem = new SequenceType (ItemType.AnyItem, Occurence.One);
+ static SequenceType singleAnyAtomic = new SequenceType (ItemType.AnyAtomicType, Occurence.One);
+
+ internal static SequenceType AnyType {
+ get { return Create (InternalPool.XsAnyType, Occurence.ZeroOrMore); }
+ }
+ internal static SequenceType SingleItem {
+ get { return singleItem; }
+ }
+ internal static SequenceType SingleAnyAtomic {
+ get { return singleAnyAtomic; }
+ }
+
+ internal static SequenceType Node {
+ get { return Create (XmlTypeCode.Node, Occurence.One); }
+ }
+ internal static SequenceType Document {
+ get { return Create (XmlTypeCode.Document, Occurence.One); }
+ }
+ internal static SequenceType Element {
+ get { return Create (XmlTypeCode.Element, Occurence.One); }
+ }
+ internal static SequenceType Attribute {
+ get { return Create (XmlTypeCode.Attribute, Occurence.One); }
+ }
+ internal static SequenceType Namespace {
+ get { return Create (XmlTypeCode.Namespace, Occurence.One); }
+ }
+ internal static SequenceType Text {
+ get { return Create (XmlTypeCode.Text, Occurence.One); }
+ }
+ internal static SequenceType XmlPI {
+ get { return Create (XmlTypeCode.ProcessingInstruction, Occurence.One); }
+ }
+ internal static SequenceType Comment {
+ get { return Create (XmlTypeCode.Comment, Occurence.One); }
+ }
+
+ internal static SequenceType AtomicString {
+ get { return Create (InternalPool.XsString, Occurence.One); }
+ }
+ internal static SequenceType Boolean {
+ get { return Create (InternalPool.XsBoolean, Occurence.One); }
+ }
+ internal static SequenceType Decimal {
+ get { return Create (InternalPool.XsDecimal, Occurence.One); }
+ }
+ internal static SequenceType Integer {
+ get { return Create (InternalPool.XsInteger, Occurence.One); }
+ }
+ internal static SequenceType Int {
+ get { return Create (InternalPool.XsInt, Occurence.One); }
+ }
+ internal static SequenceType Short {
+ get { return Create (InternalPool.XsShort, Occurence.One); }
+ }
+ internal static SequenceType UnsignedInt {
+ get { return Create (InternalPool.XsUnsignedInt, Occurence.One); }
+ }
+ internal static SequenceType UnsignedShort {
+ get { return Create (InternalPool.XsUnsignedShort, Occurence.One); }
+ }
+ internal static SequenceType Double {
+ get { return Create (InternalPool.XsDouble, Occurence.One); }
+ }
+ internal static SequenceType Single {
+ get { return Create (InternalPool.XsFloat, Occurence.One); }
+ }
+ internal static SequenceType DateTime {
+ get { return Create (InternalPool.XsDateTime, Occurence.One); }
+ }
+ internal static SequenceType QName {
+ get { return Create (InternalPool.XsQName, Occurence.One); }
+ }
+
+ internal static SequenceType IntegerList {
+ get { return Create (XmlTypeCode.Integer, Occurence.ZeroOrMore); }
+ }
+
+
+ static Hashtable standardTypes = new Hashtable ();
+
+ internal static SequenceType Create (Type cliType)
+ {
+ // typed Array
+ if (cliType.IsArray)
+ return Create (InternalPool.XmlTypeCodeFromRuntimeType (cliType.GetElementType (), true), Occurence.ZeroOrMore);
+// if (cliType.GetInterface ("System.Collections.IEnumerable") != null)
+// return Create (XmlTypeCode.Item, Occurence.ZeroOrMore);
+ if (cliType == typeof (XmlQualifiedName))
+ return QName;
+ if (cliType == typeof (XPathNavigator) || cliType.IsSubclassOf (typeof (XPathNavigator)))
+ return Node;
+ if (cliType == typeof (XPathAtomicValue))
+ return SingleAnyAtomic;
+ if (cliType == typeof (XPathItem))
+ return SingleItem;
+ // FIXME: handle Nullable type
+ return Create (InternalPool.XmlTypeCodeFromRuntimeType (cliType, true), Occurence.One);
+ }
+
+ internal static SequenceType Create (XmlTypeCode typeCode, Occurence occurence)
+ {
+ switch (typeCode) {
+ case XmlTypeCode.Item:
+ case XmlTypeCode.AnyAtomicType:
+ case XmlTypeCode.Node:
+ case XmlTypeCode.Document:
+ case XmlTypeCode.Element:
+ case XmlTypeCode.Attribute:
+ case XmlTypeCode.ProcessingInstruction:
+ case XmlTypeCode.Comment:
+ case XmlTypeCode.Namespace:
+ case XmlTypeCode.Text:
+ return new SequenceType (new ItemType (typeCode), occurence);
+ default:
+ return Create (XmlSchemaType.GetBuiltInSimpleType (typeCode), occurence);
+ }
+ }
+
+ internal static SequenceType Create (XmlSchemaType schemaType, Occurence occurence)
+ {
+ switch (schemaType.QualifiedName.Namespace) {
+ case XmlSchema.Namespace:
+ case InternalPool.XdtNamespace:
+ break;
+ default:
+ return new SequenceType (schemaType, occurence);
+ }
+
+ Hashtable cacheForType = standardTypes [schemaType] as Hashtable;
+ if (cacheForType == null) {
+ cacheForType = new Hashtable ();
+ standardTypes [schemaType] = cacheForType;
+ } else {
+ SequenceType type = cacheForType [occurence] as SequenceType;
+ if (type != null)
+ return type;
+ }
+ SequenceType t = new SequenceType (schemaType, occurence);
+ cacheForType [occurence] = t;
+ return t;
+ }
+
+ [MonoTODO]
+ internal static SequenceType ComputeCommonBase (SequenceType t1, SequenceType t2)
+ {
+ // FIXME: implement
+ // throw new NotImplementedException ();
+ return SequenceType.AnyType;
+ }
+
+ internal static bool IsNumeric (XmlTypeCode code)
+ {
+ switch (code) {
+ case XmlTypeCode.Decimal:
+ case XmlTypeCode.Float:
+ case XmlTypeCode.Double:
+ case XmlTypeCode.Integer:
+ case XmlTypeCode.NonPositiveInteger:
+ case XmlTypeCode.NegativeInteger:
+ case XmlTypeCode.Long:
+ case XmlTypeCode.Int:
+ case XmlTypeCode.Short:
+ case XmlTypeCode.Byte:
+ case XmlTypeCode.NonNegativeInteger:
+ case XmlTypeCode.UnsignedLong:
+ case XmlTypeCode.UnsignedInt:
+ case XmlTypeCode.UnsignedShort:
+ case XmlTypeCode.UnsignedByte:
+ case XmlTypeCode.PositiveInteger:
+ return true;
+ }
+ return false;
+ }
+
+ // Instance members
+
+ private SequenceType (XmlSchemaType schemaType, Occurence occurence)
+ {
+ this.schemaType = schemaType;
+ this.itemType = ItemType.AnyItem;
+ this.occurence = occurence;
+ }
+
+ internal SequenceType (ItemType itemType, Occurence occurence)
+ {
+ this.schemaType = InternalPool.XsAnyType;
+ this.itemType = itemType;
+ this.occurence = occurence;
+ }
+
+ XmlSchemaType schemaType;
+ Occurence occurence;
+ ItemType itemType;
+
+ public XmlSchemaType SchemaType {
+ get { return schemaType; }
+ }
+
+ public ItemType ItemType {
+ get { return itemType; }
+ }
+
+ public Occurence Occurence {
+ get { return occurence; }
+ }
+
+ internal bool Matches (XPathSequence iter)
+ {
+ throw new NotImplementedException ();
+ }
+
+ [MonoTODO]
+ internal bool CanConvertTo (SequenceType other)
+ {
+ // FIXME: implement precisely
+ return this == other;
+ // throw new NotImplementedException ();
+ }
+
+ internal bool CanConvert (XPathSequence iter)
+ {
+ bool occured = false;
+ bool onlyOnce = (occurence == Occurence.One || occurence == Occurence.Optional);
+ bool required = (occurence == Occurence.One || occurence == Occurence.OneOrMore);
+ foreach (XPathItem item in iter) {
+ if (occured && onlyOnce)
+ return false;
+ if (!CanConvert (item))
+ return false;
+ }
+ return occured || !required;
+ }
+
+ public bool CanConvert (XPathItem item)
+ {
+ throw new NotImplementedException ();
+ }
+
+ public bool IsInstance (XPathItem item)
+ {
+ throw new NotImplementedException ();
+ }
+
+ public XPathItem Convert (XPathItem item)
+ {
+ throw new NotImplementedException ();
+ }
+
+ public object ToRuntimeType (XPathSequence seq)
+ {
+ // FIXME: handle ZeroOrMore|OneOrMore
+ switch (occurence) {
+ case Occurence.One:
+ case Occurence.Optional:
+ if (!seq.MoveNext ())
+ return null;
+ XPathItem item = seq.Current;
+ // FIXME: should check and reject two or
+ // more items??
+ return item.TypedValue;
+ }
+ ArrayList al = new ArrayList ();
+ while (seq.MoveNext ())
+ al.Add (seq.Current.TypedValue);
+ return al.ToArray (InternalPool.RuntimeTypeFromXmlTypeCode (schemaType.TypeCode));
+// return seq;
+ }
+ }
+
+ public enum Occurence
+ {
+ One,
+ Optional,
+ ZeroOrMore,
+ OneOrMore,
+ }
+
+ #region NodeTest
+
+ public enum XPathAxisType
+ {
+ Child,
+ Descendant,
+ Attribute,
+ Self,
+ DescendantOrSelf,
+ FollowingSibling,
+ Following,
+ Parent,
+ Ancestor,
+ PrecedingSibling,
+ Preceding,
+ AncestorOrSelf,
+ Namespace // only applicable under XPath 2.0, not XQuery 1.0
+ }
+
+ public class XPathAxis
+ {
+ // FIXME: add more parameters to distinguish them
+ private XPathAxis (XPathAxisType axisType)
+ {
+ this.axisType = axisType;
+ switch (axisType) {
+ case XPathAxisType.Parent:
+ case XPathAxisType.Ancestor:
+ case XPathAxisType.AncestorOrSelf:
+ case XPathAxisType.Preceding:
+ case XPathAxisType.PrecedingSibling:
+ this.reverse = true;
+ break;
+ }
+ }
+
+ bool reverse;
+ XPathAxisType axisType;
+
+ public bool ReverseAxis {
+ get { return reverse; }
+ }
+
+ public XPathAxisType AxisType {
+ get { return axisType; }
+ }
+
+ static XPathAxis child, descendant, attribute, self,
+ descendantOrSelf, followingSibling, following,
+ parent, ancestor, precedingSibling, preceding,
+ ancestorOrSelf;
+
+ static XPathAxis ()
+ {
+ child = new XPathAxis (XPathAxisType.Child);
+ descendant = new XPathAxis (XPathAxisType.Descendant);
+ attribute = new XPathAxis (XPathAxisType.Attribute);
+ self = new XPathAxis (XPathAxisType.Self);
+ descendantOrSelf = new XPathAxis (XPathAxisType.DescendantOrSelf);
+ followingSibling = new XPathAxis (XPathAxisType.FollowingSibling);
+ following = new XPathAxis (XPathAxisType.Following);
+ parent = new XPathAxis (XPathAxisType.Parent);
+ ancestor = new XPathAxis (XPathAxisType.Ancestor);
+ precedingSibling = new XPathAxis (XPathAxisType.PrecedingSibling);
+ preceding = new XPathAxis (XPathAxisType.Preceding);
+ ancestorOrSelf = new XPathAxis (XPathAxisType.AncestorOrSelf);
+ }
+
+ public static XPathAxis Child {
+ get { return child; }
+ }
+
+ public static XPathAxis Descendant {
+ get { return descendant; }
+ }
+
+ public static XPathAxis Attribute {
+ get { return attribute; }
+ }
+
+ public static XPathAxis Self {
+ get { return self; }
+ }
+
+ public static XPathAxis DescendantOrSelf {
+ get { return descendantOrSelf; }
+ }
+
+ public static XPathAxis FollowingSibling {
+ get { return followingSibling; }
+ }
+
+ public static XPathAxis Following {
+ get { return following; }
+ }
+
+ public static XPathAxis Parent {
+ get { return parent; }
+ }
+
+ public static XPathAxis Ancestor {
+ get { return ancestor; }
+ }
+
+ public static XPathAxis PrecedingSibling {
+ get { return precedingSibling; }
+ }
+
+ public static XPathAxis Preceding {
+ get { return preceding; }
+ }
+
+ public static XPathAxis AncestorOrSelf {
+ get { return ancestorOrSelf; }
+ }
+ }
+
+ // ItemType
+ public class ItemType
+ {
+ static ItemType anyItem = new ItemType (XmlTypeCode.Item);
+ static ItemType anyAtomicType = new ItemType (XmlTypeCode.AnyAtomicType);
+
+ public static ItemType AnyItem {
+ get { return anyItem; }
+ }
+
+ public static ItemType AnyAtomicType {
+ get { return anyAtomicType; }
+ }
+
+ XmlTypeCode typeCode;
+
+ public ItemType (XmlTypeCode typeCode)
+ {
+ this.typeCode = typeCode;
+ }
+
+ public XmlTypeCode TypeCode {
+ get { return typeCode; }
+ }
+
+ internal virtual void CheckReference (XQueryASTCompiler compiler)
+ {
+ }
+ }
+
+ // KindTest
+
+ public class KindTest : ItemType
+ {
+ public KindTest (XmlTypeCode type)
+ : base (type)
+ {
+ }
+
+ internal virtual void Compile (XQueryASTCompiler compiler)
+ {
+ }
+
+ public virtual bool Matches (XPathItem item)
+ {
+ XPathNavigator nav = item as XPathNavigator;
+ if (nav == null)
+ return false;
+ // FIXME: is it true? ('untyped' means 'matches with any type' ?
+ if (item.XmlType == null)
+ return true;
+ if (item.XmlType.TypeCode != TypeCode)
+ return false;
+ return true;
+ }
+ }
+
+ public class DocumentTest : KindTest
+ {
+ ElementTest content;
+
+ public DocumentTest (ElementTest content)
+ : base (XmlTypeCode.Document)
+ {
+ this.content = content;
+ }
+
+ public ElementTest Content {
+ get { return content; }
+ }
+
+ internal override void CheckReference (XQueryASTCompiler compiler)
+ {
+ content.CheckReference (compiler);
+ }
+
+ internal override void Compile (XQueryASTCompiler compiler)
+ {
+ }
+
+ public override bool Matches (XPathItem item)
+ {
+ XPathNavigator nav = item as XPathNavigator;
+ if (nav == null)
+ return false;
+
+ if (item.XmlType.TypeCode != XmlTypeCode.Document)
+ return false;
+
+ if (Content == null)
+ return true;
+
+ nav = nav.Clone ();
+ nav.MoveToFirstChild ();
+ while (nav.NodeType != XPathNodeType.Element)
+ if (!nav.MoveToNext ())
+ return false;
+ return Content.Matches (nav);
+ }
+ }
+
+ public class ElementTest : KindTest
+ {
+ XmlQualifiedName name;
+ XmlQualifiedName typeName;
+ XmlSchemaType schemaType;
+ bool nillable;
+
+ public ElementTest (XmlQualifiedName name)
+ : base (XmlTypeCode.Element)
+ {
+ this.name = name;
+ }
+
+ public ElementTest (XmlQualifiedName name, XmlQualifiedName type, bool nillable)
+ : base (XmlTypeCode.Element)
+ {
+ this.name = name;
+ this.typeName = type;
+ this.nillable = nillable;
+ }
+
+ public XmlQualifiedName Name {
+ get { return name; }
+ }
+
+ public XmlQualifiedName TypeName {
+ get { return typeName; }
+ }
+
+ public XmlSchemaType SchemaType {
+ get {
+ return schemaType;
+ }
+ }
+
+ public bool Nillable {
+ get { return nillable; }
+ }
+
+ internal override void CheckReference (XQueryASTCompiler compiler)
+ {
+ compiler.CheckSchemaTypeName (typeName);
+ }
+
+ internal override void Compile (XQueryASTCompiler compiler)
+ {
+ schemaType = compiler.ResolveSchemaType (TypeName);
+ if (schemaType == null)
+ throw new XmlQueryCompileException ("Specified schema type was not found.");
+ }
+
+ public override bool Matches (XPathItem item)
+ {
+ XPathNavigator nav = item as XPathNavigator;
+ if (nav == null)
+ return false;
+
+ if (item.XmlType.TypeCode != XmlTypeCode.Element)
+ return false;
+
+ if (Name != XmlQualifiedName.Empty)
+ if (nav.LocalName != Name.Name || nav.NamespaceURI != Name.Namespace)
+ return false;
+
+ // FIXME: it won't be XQueryConvert.CanConvert(), but other strict-matching evaluation
+ if (SchemaType != null && !XQueryConvert.CanConvert (item, SchemaType))
+ return false;
+ // FIXME: check nillable
+
+ return true;
+ }
+ }
+
+ public class AttributeTest : KindTest
+ {
+ static AttributeTest anyAttribute;
+
+ static AttributeTest ()
+ {
+ anyAttribute = new AttributeTest (XmlQualifiedName.Empty);
+ }
+
+ public static AttributeTest AnyAttribute {
+ get { return anyAttribute; }
+ }
+
+ public AttributeTest (XmlQualifiedName name)
+ : base (XmlTypeCode.Attribute)
+ {
+ this.name = name;
+ }
+
+ public AttributeTest (XmlQualifiedName name, XmlQualifiedName typeName)
+ : base (XmlTypeCode.Attribute)
+ {
+ this.name = name;
+ this.typeName = typeName;
+ }
+
+ XmlQualifiedName name;
+ XmlQualifiedName typeName;
+ XmlSchemaType schemaType;
+
+ public XmlQualifiedName Name {
+ get { return name; }
+ }
+
+ public XmlQualifiedName TypeName {
+ get { return typeName; }
+ }
+
+ public XmlSchemaType SchemaType {
+ get { return schemaType; }
+ }
+
+ internal override void CheckReference (XQueryASTCompiler compiler)
+ {
+ compiler.CheckSchemaTypeName (typeName);
+ }
+
+ internal override void Compile (XQueryASTCompiler compiler)
+ {
+ schemaType = compiler.ResolveSchemaType (TypeName);
+ if (schemaType == null)
+ throw new XmlQueryCompileException ("Specified schema type was not found.");
+ }
+
+ public override bool Matches (XPathItem item)
+ {
+ XPathNavigator nav = item as XPathNavigator;
+ if (nav == null)
+ return false;
+
+ if (item.XmlType.TypeCode != XmlTypeCode.Attribute)
+ return false;
+
+ if (Name != XmlQualifiedName.Empty)
+ if (nav.LocalName != Name.Name || nav.NamespaceURI != Name.Namespace)
+ return false;
+
+ // FIXME: it won't be XQueryConvert.CanConvert(), but other strict-matching evaluation
+ if (SchemaType != null && !XQueryConvert.CanConvert (item, SchemaType))
+ return false;
+
+ return true;
+ }
+ }
+
+ public class XmlPITest : KindTest
+ {
+ string name;
+
+ public XmlPITest (string nameTest)
+ : base (XmlTypeCode.ProcessingInstruction)
+ {
+ this.name = nameTest;
+ }
+
+ public string Name {
+ get { return name; }
+ }
+
+ internal override void CheckReference (XQueryASTCompiler compiler)
+ {
+ }
+
+ internal override void Compile (XQueryASTCompiler compiler)
+ {
+ }
+
+ public override bool Matches (XPathItem item)
+ {
+ XPathNavigator nav = item as XPathNavigator;
+ if (nav == null)
+ return false;
+
+ if (item.XmlType.TypeCode != XmlTypeCode.ProcessingInstruction)
+ return false;
+ if (Name != String.Empty && nav.LocalName != Name)
+ return false;
+ return true;
+ }
+ }
+
+ #endregion
+}
+
+#endif
diff --git a/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XPath2Expression.cs b/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XPath2Expression.cs
new file mode 100755
index 00000000000..f4ec7fff289
--- /dev/null
+++ b/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XPath2Expression.cs
@@ -0,0 +1,2439 @@
+//
+// XPath2Expression.cs - abstract syntax tree for XPath 2.0
+//
+// Author:
+// Atsushi Enomoto <atsushi@ximian.com>
+//
+//
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+#if NET_2_0
+using System;
+using System.Collections;
+using System.Globalization;
+using System.Xml;
+using System.Xml.Query;
+using System.Xml.Schema;
+using System.Xml.XPath;
+using Mono.Xml.XQuery;
+using Mono.Xml;
+
+namespace Mono.Xml.XPath2
+{
+ public class ExprSequence : CollectionBase
+ {
+ public ExprSequence ()
+ {
+ }
+
+ public void Add (ExprSingle expr)
+ {
+ List.Add (expr);
+ }
+
+ public void AddRange (ICollection items)
+ {
+ if (items != null)
+ foreach (ExprSingle e in items)
+ List.Add (e);
+ }
+
+ public void Insert (int pos, ExprSingle expr)
+ {
+ List.Insert (pos, expr);
+ }
+
+ public ExprSingle this [int i] {
+ get { return List [i] as ExprSingle; }
+ set { List [i] = value; }
+ }
+
+ internal void CheckReference (XQueryASTCompiler compiler)
+ {
+ foreach (ExprSingle expr in List)
+ expr.CheckReference (compiler);
+ }
+ }
+
+ public abstract partial class ExprSingle
+ {
+ internal abstract void CheckReference (XQueryASTCompiler compiler);
+
+#region CompileAndEvaluate
+ internal static readonly XPathAtomicValue AtomicTrue = new XPathAtomicValue (true, InternalPool.XsBoolean);
+ internal static readonly XPathAtomicValue AtomicFalse = new XPathAtomicValue (false, InternalPool.XsBoolean);
+
+ XQueryStaticContext ctx;
+
+ internal ExprSingle Compile (XQueryASTCompiler compiler)
+ {
+ this.ctx = ctx;
+ return CompileCore (compiler);
+ }
+
+ // If internal&&protected is available in C#, it is the best signature.
+ internal abstract ExprSingle CompileCore (XQueryASTCompiler compiler);
+
+ internal XQueryStaticContext Context {
+ get { return ctx; }
+ }
+
+ public abstract SequenceType StaticType { get; }
+
+ /** <summary>
+ This is the core part of ExprSingle. It is
+ generally used to evaluate expression and returns
+ XPathItem sequence (iterator). The result is unordered
+ */
+ public abstract XPathSequence Evaluate (XPathSequence iter);
+
+ public virtual XPathSequence EvaluateOrdered (XPathSequence iter)
+ {
+ if (RequireSorting) {
+ ArrayList al = new ArrayList ();
+ foreach (XPathItem item in Evaluate (iter))
+ al.Add (item);
+ return new ListIterator (iter.Context, al);
+ }
+ else
+ return Evaluate (iter);
+ }
+
+ public virtual void Serialize (XPathSequence iter)
+ {
+ XmlWriter w = iter.Context.Writer;
+ XPathSequence result = Evaluate (iter);
+ bool initial = true;
+ foreach (XPathItem item in result) {
+ if (initial)
+ initial = false;
+ else
+ w.WriteWhitespace (" ");
+ WriteXPathItem (item, w);
+ }
+ }
+
+ private void WriteXPathItem (XPathItem item, XmlWriter w)
+ {
+ if (item.IsNode) {
+ XPathNavigator nav = item as XPathNavigator;
+ if (w.WriteState != WriteState.Start && nav.NodeType == XPathNodeType.Root)
+ throw new XmlQueryException ("Current output can not accept root node.");
+ if (w.WriteState == WriteState.Attribute)
+ w.WriteString (nav.Value);
+ else
+ w.WriteNode (nav, false);
+ } else
+ w.WriteString (item.Value);
+ }
+
+ // get EBV (fn:boolean())
+ public virtual bool EvaluateAsBoolean (XPathSequence iter)
+ {
+ XPathSequence result = Evaluate (iter);
+ if (!result.MoveNext ())
+ return false;
+ XPathItem v = result.Current;
+ if (v is XPathNavigator)
+ return true;
+ if (result.MoveNext ())
+ return true;
+ switch (v.XmlType.TypeCode) {
+ case XmlTypeCode.Boolean:
+ return v.ValueAsBoolean;
+ case XmlTypeCode.String:
+ case XmlTypeCode.UntypedAtomic:
+ return v.Value != String.Empty;
+ case XmlTypeCode.Float:
+ return v.ValueAsSingle != Single.NaN && v.ValueAsSingle != 0.0;
+ case XmlTypeCode.Double:
+ return v.ValueAsDouble != Double.NaN && v.ValueAsSingle != 0.0;
+ case XmlTypeCode.Decimal:
+ return v.ValueAsDecimal != 0;
+ case XmlTypeCode.Integer:
+ case XmlTypeCode.NonPositiveInteger:
+ case XmlTypeCode.NegativeInteger:
+ case XmlTypeCode.Long:
+ case XmlTypeCode.Int:
+ case XmlTypeCode.Short:
+ case XmlTypeCode.Byte:
+ case XmlTypeCode.UnsignedInt:
+ case XmlTypeCode.UnsignedShort:
+ case XmlTypeCode.UnsignedByte:
+ return v.ValueAsInt64 != 0;
+ case XmlTypeCode.NonNegativeInteger:
+ case XmlTypeCode.UnsignedLong:
+ case XmlTypeCode.PositiveInteger:
+ return (ulong) (v.ValueAs (typeof (ulong))) != 0;
+ }
+ // otherwise, return true
+ return true;
+ }
+
+ public virtual int EvaluateAsInt (XPathSequence iter)
+ {
+ XPathAtomicValue v = Atomize (Evaluate (iter));
+ return v != null ? v.ValueAsInt32 : 0;
+ }
+
+ public virtual string EvaluateAsString (XPathSequence iter)
+ {
+ XPathAtomicValue v = Atomize (Evaluate (iter));
+ return v != null ? v.Value : String.Empty;
+ }
+
+ public static XPathAtomicValue Atomize (XPathItem item)
+ {
+ XPathNavigator nav = item as XPathNavigator;
+ if (nav != null) {
+ if (nav.SchemaInfo != null) {
+ XmlSchemaType type = nav.SchemaInfo.SchemaType;
+ XmlSchemaComplexType ct = type as XmlSchemaComplexType;
+ if (ct != null && ct.ContentType == XmlSchemaContentType.ElementOnly)
+ throw new XmlQueryException ("An attempt to get atomized value against element-only node happend.");
+ switch (type.TypeCode) {
+ case XmlTypeCode.Item:
+// case XmlTypeCode.Untyped:
+ type = XmlSchemaType.GetBuiltInSimpleType (XmlTypeCode.UntypedAtomic);
+ break;
+ }
+ return new XPathAtomicValue (nav.TypedValue, type);
+ }
+ else
+ return new XPathAtomicValue (nav.Value, InternalPool.XdtUntypedAtomic);
+ }
+ else
+ return (XPathAtomicValue) item;
+ }
+
+ // FIXME: What if iter contains list value?
+ public static XPathAtomicValue Atomize (XPathSequence iter)
+ {
+ if (!iter.MoveNext ())
+ return null;
+ XPathNavigator nav = iter.Current as XPathNavigator;
+ if (nav != null) {
+ // FIXME: is it really always untypedAtomic?
+ // It might be complex content.
+ XmlSchemaType type = nav.SchemaInfo == null ? InternalPool.XdtUntypedAtomic : nav.SchemaInfo.SchemaType;
+ return new XPathAtomicValue (nav.TypedValue, type);
+ }
+ else
+ return (XPathAtomicValue) iter.Current;
+ }
+
+ public virtual XPathAtomicValue EvaluateAsAtomic (XPathSequence iter)
+ {
+ return Atomize (Evaluate (iter));
+ }
+
+ public virtual bool RequireSorting {
+ get { return false; }
+ }
+#endregion
+ }
+
+ // FLWORExpr
+
+ internal partial class FLWORExpr : ExprSingle
+ {
+ public FLWORExpr (ForLetClauseCollection forlet, ExprSequence whereClause, OrderSpecList orderBy, ExprSingle ret)
+ {
+ this.fl = forlet;
+ if (whereClause != null)
+ this.whereClause = new ParenthesizedExpr (whereClause);
+ this.orderBy = orderBy;
+ this.ret = ret;
+ }
+
+ ForLetClauseCollection fl;
+ ExprSingle whereClause;
+ OrderSpecList orderBy;
+ ExprSingle ret;
+
+ public ForLetClauseCollection ForLetClauses {
+ get { return fl; }
+ }
+
+ public ExprSingle WhereClause {
+ get { return whereClause; }
+ }
+
+ public OrderSpecList OrderBy {
+ get { return orderBy; }
+ }
+
+ public ExprSingle ReturnExpr {
+ get { return ret; }
+ set { ret = value; }
+ }
+
+ // ExprSingle Overrides
+
+ internal override void CheckReference (XQueryASTCompiler compiler)
+ {
+ foreach (ForLetClause flc in fl)
+ foreach (ForLetSingleBody single in flc)
+ single.CheckReference (compiler);
+ if (whereClause != null)
+ whereClause.CheckReference (compiler);
+ if (orderBy != null)
+ foreach (OrderSpec os in orderBy)
+ os.Expression.CheckReference (compiler);
+ ret.CheckReference (compiler);
+ }
+
+#region CompileAndEvaluate
+ internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
+ {
+ foreach (ForLetClause flc in ForLetClauses) {
+ foreach (ForLetSingleBody flsb in flc) {
+ flsb.Expression = flsb.Expression.Compile (compiler);
+ if (flsb.ReturnType != null)
+ compiler.CheckType (flsb.Expression, flsb.ReturnType);
+ }
+ }
+ if (WhereClause != null)
+ whereClause = whereClause.Compile (compiler);
+ if (OrderBy != null)
+ foreach (OrderSpec os in OrderBy)
+ os.Expression = os.Expression.Compile (compiler);
+ ReturnExpr = ReturnExpr.Compile (compiler);
+
+ return this;
+ }
+
+ public override SequenceType StaticType {
+ get { return ReturnExpr.StaticType; }
+ }
+
+ public override XPathSequence Evaluate (XPathSequence iter)
+ {
+ return new FLWORIterator (iter, this);
+ }
+#endregion
+ }
+
+ internal class ForLetClauseCollection : CollectionBase
+ {
+ public void Add (ForLetClause clause)
+ {
+ List.Add (clause);
+ }
+
+ public void Insert (int pos, ForLetClause clause)
+ {
+ List.Insert (pos, clause);
+ }
+
+ public ForLetClause this [int i] {
+ get { return (ForLetClause) List [i]; }
+ }
+ }
+
+ internal class OrderSpecList : CollectionBase
+ {
+ bool isStable;
+
+ public OrderSpecList ()
+ {
+ }
+
+ public bool IsStable {
+ get { return isStable; }
+ set { isStable = value; }
+ }
+
+ public void Insert (int pos, OrderSpec os)
+ {
+ List.Insert (pos, os);
+ }
+
+ public void Add (OrderSpec spec)
+ {
+ List.Add (spec);
+ }
+
+ public OrderSpec this [int i] {
+ get { return (OrderSpec) List [i]; }
+ }
+ }
+
+ internal class OrderSpec
+ {
+ public OrderSpec (ExprSingle expr, OrderModifier modifier)
+ {
+ this.expr = expr;
+ this.mod = modifier;
+ }
+
+ ExprSingle expr;
+ OrderModifier mod;
+
+ public ExprSingle Expression {
+ get {return expr; }
+ set { expr = value; }
+ }
+
+ public OrderModifier Modifier {
+ get { return mod; }
+ set { mod = value; }
+ }
+ }
+
+ internal class OrderModifier
+ {
+ public OrderModifier (XmlSortOrder order, XmlSortOrder emptyOrder, string collation)
+ {
+ this.sortOrder = sortOrder;
+ this.emptyOrder = emptyOrder;
+ if (collation != null)
+ this.coll = new CultureInfo (collation);
+ }
+
+ XmlSortOrder sortOrder;
+ XmlSortOrder emptyOrder;
+ CultureInfo coll;
+
+ public XmlSortOrder SortOrder {
+ get { return sortOrder; }
+ }
+
+ public XmlSortOrder EmptyOrder {
+ get { return emptyOrder; }
+ }
+
+ public CultureInfo Collation {
+ get { return coll; }
+ }
+ }
+
+ internal class ForLetClause : CollectionBase
+ {
+ public ForLetSingleBody this [int i] {
+ get { return (ForLetSingleBody) List [i]; }
+ }
+ }
+
+ internal class ForClause : ForLetClause
+ {
+ public ForClause ()
+ {
+ }
+
+ public void Insert (int pos, ForSingleBody body)
+ {
+ List.Insert (pos, body);
+ }
+
+ public void Add (ForSingleBody body)
+ {
+ List.Add (body);
+ }
+ }
+
+ internal class LetClause : ForLetClause
+ {
+ public LetClause ()
+ {
+ }
+
+ public void Insert (int pos, LetSingleBody body)
+ {
+ List.Insert (pos, body);
+ }
+
+ public void Add (LetSingleBody body)
+ {
+ List.Add (body);
+ }
+ }
+
+ internal abstract class ForLetSingleBody
+ {
+ XmlQualifiedName varName;
+ SequenceType type;
+ ExprSingle expr;
+
+ public ForLetSingleBody (XmlQualifiedName varName, SequenceType type, ExprSingle expr)
+ {
+ this.varName = varName;
+ this.type = type;
+ this.expr = expr;
+ }
+
+ public XmlQualifiedName VarName {
+ get { return varName; }
+ }
+
+ public SequenceType ReturnType {
+ get { return type; }
+ }
+
+ public ExprSingle Expression {
+ get { return expr; }
+ set { expr = value; }
+ }
+
+ internal void CheckReference (XQueryASTCompiler compiler)
+ {
+ if (type != null)
+ compiler.CheckSchemaType (type);
+ expr.CheckReference (compiler);
+ }
+ }
+
+ internal class ForSingleBody : ForLetSingleBody
+ {
+ public ForSingleBody (XmlQualifiedName varName, SequenceType type, XmlQualifiedName positionalVar, ExprSingle expr)
+ : base (varName, type, expr)
+ {
+ this.positionalVar = positionalVar;
+ }
+
+ XmlQualifiedName positionalVar;
+
+ public XmlQualifiedName PositionalVar {
+ get { return positionalVar; }
+ }
+ }
+
+ internal class LetSingleBody : ForLetSingleBody
+ {
+ public LetSingleBody (XmlQualifiedName varName, SequenceType type, ExprSingle expr)
+ : base (varName, type, expr)
+ {
+ }
+ }
+
+ // QuantifiedExpr
+
+ internal class QuantifiedExpr : ExprSingle
+ {
+ QuantifiedExprBodyList body;
+ ExprSingle satisfies;
+ bool every;
+
+ public QuantifiedExpr (bool every, QuantifiedExprBodyList body, ExprSingle satisfies)
+ {
+ this.every = every;
+ this.body = body;
+ this.satisfies = satisfies;
+ }
+
+ public bool Every {
+ get { return every; }
+ }
+
+ public QuantifiedExprBodyList BodyList {
+ get { return body; }
+ }
+
+ public ExprSingle Satisfies {
+ get { return satisfies; }
+ set { satisfies = value; }
+ }
+
+ internal override void CheckReference (XQueryASTCompiler compiler)
+ {
+ foreach (QuantifiedExprBody one in body) {
+ if (one.Type != null)
+ compiler.CheckSchemaType (one.Type);
+ one.Expression.CheckReference (compiler);
+ }
+ Satisfies.CheckReference (compiler);
+ }
+
+#region CompileAndEvaluate
+ internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
+ {
+ Satisfies = Satisfies.Compile (compiler);
+ for (int i = 0; i < BodyList.Count; i++) {
+ BodyList [i].Expression = BodyList [i].Expression.Compile (compiler);
+ if (BodyList [i].Type != null)
+ compiler.CheckType (BodyList [i].Expression, BodyList [i].Type);
+ }
+ return this;
+ }
+
+ public override SequenceType StaticType {
+ get { return SequenceType.Boolean; }
+ }
+
+ public override XPathSequence Evaluate (XPathSequence iter)
+ {
+ return new SingleItemIterator (EvaluateAsBoolean (iter) ? AtomicTrue : AtomicFalse, iter.Context);
+ }
+
+ public override bool EvaluateAsBoolean (XPathSequence iter)
+ {
+ return EvaluateQuantification (iter, BodyList.GetEnumerator ());
+ }
+
+ private bool EvaluateQuantification (XPathSequence iter, IEnumerator bodies)
+ {
+ if (bodies.MoveNext ()) {
+ QuantifiedExprBody qb = bodies.Current as QuantifiedExprBody;
+ XPathSequence seq = qb.Expression.Evaluate (iter);
+ bool passed = false;
+ foreach (XPathItem item in seq) {
+ passed = true;
+ // FIXME: consider qb.Type
+ try {
+ iter.Context.PushVariable (qb.VarName, item);
+ if (EvaluateQuantification (iter, bodies)) {
+ if (!Every)
+ return true;
+ }
+ else if (Every)
+ return false;
+ } finally {
+ iter.Context.PopVariable ();
+ }
+ }
+ return passed;
+ }
+ return Satisfies.EvaluateAsBoolean (iter);
+ }
+#endregion
+ }
+
+ internal class QuantifiedExprBodyList : CollectionBase
+ {
+ public QuantifiedExprBodyList ()
+ {
+ }
+
+ public void Add (QuantifiedExprBody body)
+ {
+ List.Add (body);
+ }
+
+ public void Insert (int pos, QuantifiedExprBody body)
+ {
+ List.Insert (pos, body);
+ }
+
+ public QuantifiedExprBody this [int i] {
+ get { return (QuantifiedExprBody) List [i]; }
+ }
+ }
+
+ internal class QuantifiedExprBody
+ {
+ private XmlQualifiedName varName;
+ private SequenceType type;
+ private ExprSingle expr;
+
+ public QuantifiedExprBody (XmlQualifiedName varName,
+ SequenceType type, ExprSingle expr)
+ {
+ this.varName = varName;
+ this.type = type ;
+ this.expr = expr;
+ }
+
+ public XmlQualifiedName VarName {
+ get { return varName; }
+ }
+
+ public SequenceType Type {
+ get { return type; }
+ }
+
+ public ExprSingle Expression {
+ get { return expr; }
+ set { expr = value; }
+ }
+ }
+
+ // TypeswitchExpr
+
+ internal class TypeswitchExpr : ExprSingle
+ {
+ ExprSequence switchExpr;
+ CaseClauseList caseList;
+ XmlQualifiedName defaultVarName;
+ ExprSingle defaultReturn;
+
+ public TypeswitchExpr (ExprSequence switchExpr, CaseClauseList caseList, XmlQualifiedName defaultVarName, ExprSingle defaultReturn)
+ {
+ this.switchExpr = switchExpr;
+ this.caseList = caseList;
+ this.defaultVarName = defaultVarName;
+ this.defaultReturn = defaultReturn;
+ }
+
+ public ExprSequence SwitchExpr {
+ get { return switchExpr; }
+ }
+
+ public CaseClauseList Cases {
+ get { return caseList; }
+ }
+
+ public XmlQualifiedName DefaultVarName {
+ get { return defaultVarName; }
+ }
+
+ public ExprSingle DefaultReturn {
+ get { return defaultReturn; }
+ set { defaultReturn = value; }
+ }
+
+ internal override void CheckReference (XQueryASTCompiler compiler)
+ {
+ switchExpr.CheckReference (compiler);
+ foreach (CaseClause cc in caseList) {
+ compiler.CheckSchemaType (cc.Type);
+ cc.Expr.CheckReference (compiler);
+ }
+ defaultReturn.CheckReference (compiler);
+ }
+
+#region CompileAndEvaluate
+ internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
+ {
+ for (int i = 0; i < SwitchExpr.Count; i++)
+ SwitchExpr [i] = SwitchExpr [i].Compile (compiler);
+ foreach (CaseClause cc in Cases)
+ cc.Expr = cc.Expr.Compile (compiler);
+ DefaultReturn = DefaultReturn.Compile (compiler);
+ return this;
+ }
+
+ // FIXME: it can be optimized by checking all case clauses.
+ public override SequenceType StaticType {
+ get { return SequenceType.AnyType; }
+ }
+
+ public override XPathSequence Evaluate (XPathSequence iter)
+ {
+ // FIXME: should move to iterator?
+ XPathSequence cond = new ExprSequenceIterator (iter, SwitchExpr);
+ XPathSequence ret = null;
+
+ foreach (CaseClause ccc in Cases) {
+ if (ccc.Type.Matches (cond)) {
+ if (ccc.VarName != XmlQualifiedName.Empty)
+ iter.Context.PushVariable (ccc.VarName, cond);
+ ret = ccc.Expr.Evaluate (iter);
+ // FIXME: The design should make sure that in-scope variables are held on actual iteration.
+ if (ccc.VarName != XmlQualifiedName.Empty)
+ iter.Context.PopVariable ();
+ return ret;
+ }
+ }
+
+ if (DefaultVarName != XmlQualifiedName.Empty)
+ iter.Context.PushVariable (DefaultVarName, cond);
+ ret = DefaultReturn.Evaluate (iter);
+ if (DefaultVarName != XmlQualifiedName.Empty)
+ iter.Context.PopVariable ();
+ return ret;
+ }
+#endregion
+ }
+
+ internal class CaseClauseList : CollectionBase
+ {
+ public void Insert (int pos, CaseClause cc)
+ {
+ List.Insert (pos, cc);
+ }
+
+ public void Add (CaseClause cc)
+ {
+ List.Add (cc);
+ }
+
+ public CaseClause this [int i] {
+ get { return (CaseClause) List [i]; }
+ }
+ }
+
+ internal class CaseClause
+ {
+ public CaseClause (SequenceType type, ExprSingle expr, XmlQualifiedName varName)
+ {
+ this.type = type;
+ this.expr = expr;
+ this.varName = varName;
+ }
+
+ SequenceType type;
+ ExprSingle expr;
+ XmlQualifiedName varName;
+
+ public SequenceType Type {
+ get { return type; }
+ }
+
+ public ExprSingle Expr {
+ get { return expr; }
+ set { expr = value; }
+ }
+
+ public XmlQualifiedName VarName {
+ get { return varName; }
+ set { varName = value; }
+ }
+ }
+
+ // IfExpr
+
+ internal class IfExpr : ExprSingle
+ {
+ public IfExpr (ExprSequence condition, ExprSingle trueExpr, ExprSingle falseExpr)
+ {
+ this.condition = new ParenthesizedExpr (condition);
+ this.trueExpr = trueExpr;
+ this.falseExpr = falseExpr;
+ }
+
+ ExprSingle condition;
+ ExprSingle trueExpr;
+ ExprSingle falseExpr;
+
+ public ExprSingle Condition {
+ get { return condition; }
+ set { condition = value; }
+ }
+
+ public ExprSingle TrueExpr {
+ get { return trueExpr; }
+ set { trueExpr = value; }
+ }
+
+ public ExprSingle FalseExpr {
+ get { return falseExpr; }
+ set { falseExpr = value; }
+ }
+
+ internal override void CheckReference (XQueryASTCompiler compiler)
+ {
+ condition.CheckReference (compiler);
+ trueExpr.CheckReference (compiler);
+ falseExpr.CheckReference (compiler);
+ }
+
+#region CompileAndEvaluate
+ SequenceType computedReturnType;
+
+ internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
+ {
+ condition = condition.Compile (compiler);
+ // FIXME: check if condition is constant, and returns trueExpr or falseExpr
+ TrueExpr = TrueExpr.Compile (compiler);
+ FalseExpr = FalseExpr.Compile (compiler);
+ return this;
+ }
+
+ public override SequenceType StaticType {
+ get {
+ if (Context == null)
+ return SequenceType.AnyType;
+ if (computedReturnType == null)
+ computedReturnType = SequenceType.ComputeCommonBase (TrueExpr.StaticType, FalseExpr.StaticType);
+ return computedReturnType;
+ }
+ }
+
+ public override XPathSequence Evaluate (XPathSequence iter)
+ {
+ if (condition.EvaluateAsBoolean (iter))
+ return TrueExpr.Evaluate (iter);
+ return FalseExpr.Evaluate (iter);
+ }
+#endregion
+
+ }
+
+ // logical expr
+
+ internal abstract class BinaryOperationExpr : ExprSingle
+ {
+ protected BinaryOperationExpr (ExprSingle left, ExprSingle right)
+ {
+ this.left = left;
+ this.right = right;
+ }
+
+ ExprSingle left, right;
+
+ public ExprSingle Left {
+ get { return left; }
+ set { left = value; }
+ }
+
+ public ExprSingle Right{
+ get { return right; }
+ set { right = value; }
+ }
+
+ internal override void CheckReference (XQueryASTCompiler compiler)
+ {
+ left.CheckReference (compiler);
+ right.CheckReference (compiler);
+ }
+
+#region CompileAndEvaluate
+ internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
+ {
+ Left = Left.Compile (compiler);
+ Right = Right.Compile (compiler);
+ return this;
+ }
+#endregion
+
+ }
+
+ internal class OrExpr : BinaryOperationExpr
+ {
+ public OrExpr (ExprSingle left, ExprSingle right)
+ : base (left, right)
+ {
+ }
+
+#region CompileAndEvaluate
+ internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
+ {
+ base.CompileCore (compiler);
+ // FIXME: check constant value and return true or false
+ return this;
+ }
+
+ public override SequenceType StaticType {
+ get { return SequenceType.Boolean; }
+ }
+
+ public override bool EvaluateAsBoolean (XPathSequence iter)
+ {
+ return Left.EvaluateAsBoolean (iter) || Right.EvaluateAsBoolean (iter);
+ }
+
+ public override XPathSequence Evaluate (XPathSequence iter)
+ {
+ return new SingleItemIterator (EvaluateAsBoolean (iter) ?AtomicTrue : AtomicFalse, iter.Context);
+ }
+
+ /*
+ - compiler -
+ return leftExprBool (context) || rightExprBool (context);
+ */
+#endregion
+ }
+
+ internal class AndExpr : BinaryOperationExpr
+ {
+ public AndExpr (ExprSingle left, ExprSingle right)
+ : base (left, right)
+ {
+ }
+
+#region CompileAndEvaluate
+ internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
+ {
+ base.CompileCore (compiler);
+ // FIXME: check constant value and return true or false
+ return this;
+ }
+
+ public override SequenceType StaticType {
+ get { return SequenceType.Boolean; }
+ }
+
+ public override bool EvaluateAsBoolean (XPathSequence iter)
+ {
+ return Left.EvaluateAsBoolean (iter) && Right.EvaluateAsBoolean (iter);
+ }
+
+ public override XPathSequence Evaluate (XPathSequence iter)
+ {
+ return new SingleItemIterator (EvaluateAsBoolean (iter) ? AtomicTrue : AtomicFalse, iter.Context);
+ }
+
+ /*
+ - compiler -
+ return leftExprBool (context) && rightExprBool (context);
+ */
+#endregion
+ }
+
+ // TypeOperation expr
+
+ internal abstract class TypeOperationExpr : ExprSingle
+ {
+ protected TypeOperationExpr (ExprSingle expr, SequenceType type)
+ {
+ this.expr = expr;
+ this.type = type;
+ }
+
+ ExprSingle expr;
+ SequenceType type;
+
+ public ExprSingle Expr {
+ get { return expr; }
+ set { expr = value; }
+ }
+
+ public SequenceType TargetType {
+ get { return type; }
+ }
+
+ internal override void CheckReference (XQueryASTCompiler compiler)
+ {
+ expr.CheckReference (compiler);
+ compiler.CheckSchemaType (type);
+ }
+ }
+
+ internal abstract class AtomicTypeOperationExpr : ExprSingle
+ {
+ protected AtomicTypeOperationExpr (ExprSingle expr, XmlTypeCode type, bool optional)
+ {
+ this.expr = expr;
+ this.targetType = SequenceType.Create (type, optional ? Occurence.Optional : Occurence.One);
+ }
+
+ ExprSingle expr;
+ SequenceType targetType;
+
+ internal ExprSingle Expr {
+ get { return expr; }
+ set { expr = value; }
+ }
+
+/*
+ public XmlTypeCode TypeCode {
+ get { return typeCode; }
+ }
+
+ public bool Optional {
+ get { return optional; }
+ }
+*/
+ internal SequenceType TargetType {
+ get { return targetType; }
+ }
+
+ internal override void CheckReference (XQueryASTCompiler compiler)
+ {
+ expr.CheckReference (compiler);
+ }
+ }
+
+ internal class InstanceOfExpr : TypeOperationExpr
+ {
+ public InstanceOfExpr (ExprSingle expr, SequenceType type)
+ : base (expr, type)
+ {
+ }
+
+#region CompileAndEvaluate
+ internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
+ {
+ Expr = Expr.Compile (compiler);
+ // FIXME: check return type and if it never matches then return false
+ return this;
+ }
+
+ public override SequenceType StaticType {
+ get { return SequenceType.Boolean; }
+ }
+
+ public override bool EvaluateAsBoolean (XPathSequence iter)
+ {
+ bool occured = false;
+ bool onlyOnce = (TargetType.Occurence == Occurence.One || TargetType.Occurence == Occurence.Optional);
+ bool required = (TargetType.Occurence == Occurence.One || TargetType.Occurence == Occurence.OneOrMore);
+ foreach (XPathItem item in iter) {
+ if (occured && onlyOnce)
+ return false;
+ if (!TargetType.IsInstance (item))
+ return false;
+ }
+ return occured || !required;
+ }
+
+ public override XPathSequence Evaluate (XPathSequence iter)
+ {
+ return new SingleItemIterator (EvaluateAsBoolean (iter) ? AtomicTrue : AtomicFalse, iter.Context);
+ }
+#endregion
+ }
+
+ internal class TreatExpr : TypeOperationExpr
+ {
+ public TreatExpr (ExprSingle expr, SequenceType type)
+ : base (expr, type)
+ {
+ }
+
+#region CompileAndEvaluate
+ internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
+ {
+ Expr = Expr.Compile (compiler);
+ // FIXME: check return type and if it never matches then return false
+ return this;
+ }
+
+ public override SequenceType StaticType {
+ get { return SequenceType.AnyType; }
+ }
+
+ public override XPathSequence Evaluate (XPathSequence iter)
+ {
+ if (TargetType.CanConvert (iter))
+ return iter;
+ else
+ throw new XmlQueryException (String.Format ("Cannot treat as {1}", TargetType));
+ }
+#endregion
+ }
+
+ internal class CastableExpr : AtomicTypeOperationExpr
+ {
+ public CastableExpr (ExprSingle expr, XmlTypeCode atomicType, bool optional)
+ : base (expr, atomicType, optional)
+ {
+ }
+
+#region CompileAndEvaluate
+ internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
+ {
+ Expr = Expr.Compile (compiler);
+ // FIXME: check return type and if it never matches then return boolean
+ return this;
+ }
+
+ public override SequenceType StaticType {
+ get { return SequenceType.Boolean; }
+ }
+
+ public override XPathSequence Evaluate (XPathSequence iter)
+ {
+ return new SingleItemIterator (new XPathAtomicValue (EvaluateAsBoolean (iter), InternalPool.XsBoolean), iter.Context);
+ }
+
+ public override bool EvaluateAsBoolean (XPathSequence iter)
+ {
+ bool occured = false;
+ bool onlyOnce = (TargetType.Occurence == Occurence.One || TargetType.Occurence == Occurence.Optional);
+ bool required = (TargetType.Occurence == Occurence.One || TargetType.Occurence == Occurence.OneOrMore);
+ foreach (XPathItem item in iter) {
+ if (occured && onlyOnce)
+ return false;
+ if (!TargetType.CanConvert (item))
+ return false;
+ }
+ return occured || !required;
+ }
+#endregion
+ }
+
+ internal class CastExpr : AtomicTypeOperationExpr
+ {
+ public CastExpr (ExprSingle expr, XmlTypeCode atomicType, bool optional)
+ : base (expr, atomicType, optional)
+ {
+ }
+
+#region CompileAndEvaluate
+ internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
+ {
+ Expr = Expr.Compile (compiler);
+ // FIXME: check return type and if it never matches then return boolean
+ return this;
+ }
+
+ public override SequenceType StaticType {
+ get { return TargetType; }
+ }
+
+ public override XPathSequence Evaluate (XPathSequence iter)
+ {
+ if (TargetType.CanConvert (iter))
+ return new ConvertingIterator (iter, TargetType);
+ else
+ throw new XmlQueryException (String.Format ("Cannot cast as {1}", TargetType));
+ }
+#endregion
+ }
+
+ // ComparisonExpr
+
+ internal class ComparisonExpr : BinaryOperationExpr
+ {
+ public ComparisonExpr (ExprSingle left, ExprSingle right, ComparisonOperator oper)
+ : base (left, right)
+ {
+ this.oper = oper;
+ }
+
+ ComparisonOperator oper;
+
+ public ComparisonOperator Operation {
+ get { return oper; }
+ }
+
+#region CompileAndEvaluate
+ internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
+ {
+ Left = Left.Compile (compiler);
+ Right = Right.Compile (compiler);
+ // FIXME: check return type and if it never matches then return boolean
+ return this;
+ }
+
+ public override SequenceType StaticType {
+ get { return SequenceType.Boolean; }
+ }
+
+ public override XPathSequence Evaluate (XPathSequence iter)
+ {
+ bool isEmpty;
+ bool result = EvaluateAsBoolean (iter, out isEmpty);
+ if (isEmpty)
+ return new XPathEmptySequence (iter.Context);
+ return new SingleItemIterator (result ? AtomicTrue : AtomicFalse, iter.Context);
+ }
+
+ public override bool EvaluateAsBoolean (XPathSequence iter)
+ {
+ bool isEmpty;
+ return EvaluateAsBoolean (iter, out isEmpty);
+ }
+
+ private bool EvaluateAsBoolean (XPathSequence iter, out bool isEmpty)
+ {
+ XPathSequence lseq, rseq;
+ isEmpty = false;
+
+ switch (Operation) {
+ // FIXME: it is curious but currently gmcs requires full typename.
+ case Mono.Xml.XPath2.ComparisonOperator.ValueEQ:
+ case Mono.Xml.XPath2.ComparisonOperator.ValueNE:
+ case Mono.Xml.XPath2.ComparisonOperator.ValueLT:
+ case Mono.Xml.XPath2.ComparisonOperator.ValueLE:
+ case Mono.Xml.XPath2.ComparisonOperator.ValueGT:
+ case Mono.Xml.XPath2.ComparisonOperator.ValueGE:
+ XPathItem itemVL = ExamineOneItem (Left.Evaluate (iter));
+ XPathItem itemVR = ExamineOneItem (Right.Evaluate (iter));
+ if (itemVL == null || itemVR == null) {
+ isEmpty = true;
+ return false;
+ }
+ return CompareAtomic (itemVL, itemVR);
+
+ case Mono.Xml.XPath2.ComparisonOperator.GeneralEQ:
+ case Mono.Xml.XPath2.ComparisonOperator.GeneralNE:
+ case Mono.Xml.XPath2.ComparisonOperator.GeneralLT:
+ case Mono.Xml.XPath2.ComparisonOperator.GeneralLE:
+ case Mono.Xml.XPath2.ComparisonOperator.GeneralGT:
+ case Mono.Xml.XPath2.ComparisonOperator.GeneralGE:
+ lseq = Left.Evaluate (iter);
+ rseq = Right.Evaluate (iter);
+ foreach (XPathItem itemGL in lseq) {
+ foreach (XPathItem itemGR in rseq.Clone ()) {
+ if (CompareAtomic (itemGL, itemGR))
+ return true;
+ }
+ }
+ return false;
+
+ case Mono.Xml.XPath2.ComparisonOperator.NodeIs:
+ case Mono.Xml.XPath2.ComparisonOperator.NodeFWD:
+ case Mono.Xml.XPath2.ComparisonOperator.NodeBWD:
+ XPathNavigator lnav = ExamineOneNode (Left.Evaluate (iter));
+ XPathNavigator rnav = ExamineOneNode (Right.Evaluate (iter));
+ if (lnav == null || rnav == null) {
+ isEmpty = true;
+ return false;
+ }
+ switch (Operation) {
+ case Mono.Xml.XPath2.ComparisonOperator.NodeIs:
+ return lnav.IsSamePosition (rnav);
+ case Mono.Xml.XPath2.ComparisonOperator.NodeFWD:
+ return lnav.ComparePosition (rnav) == XmlNodeOrder.Before;
+ case Mono.Xml.XPath2.ComparisonOperator.NodeBWD:
+ return lnav.ComparePosition (rnav) == XmlNodeOrder.After;
+ }
+ break;
+ }
+ throw new SystemException ("XQuery internal error: should not happen.");
+ }
+
+ // returns null if sequence was empty
+ private XPathItem ExamineOneItem (XPathSequence seq)
+ {
+ if (!seq.MoveNext ())
+ return null;
+ XPathItem item = seq.Current;
+ if (seq.MoveNext ())
+ throw new XmlQueryException ("Operand of value comparison expression must be evaluated as a sequence that contains exactly one item.");
+ return item;
+ }
+
+ // returns null if sequence was empty
+ private XPathNavigator ExamineOneNode (XPathSequence seq)
+ {
+ if (!seq.MoveNext ())
+ return null;
+ XPathNavigator nav = seq.Current as XPathNavigator;
+ if (nav == null || seq.MoveNext ())
+ throw new XmlQueryException ("Operand of node comparison expression must be evaluated as a sequence that contains exactly one node.");
+ return nav;
+ }
+
+ private bool CompareAtomic (XPathItem itemL, XPathItem itemR)
+ {
+ XmlSchemaSimpleType ua = InternalPool.XdtUntypedAtomic;
+ XmlSchemaSimpleType str = InternalPool.XsString;
+ // FIXME: XPathNavigator might be complex content.
+ bool uaL = itemL.XmlType == null || itemL.XmlType == ua;
+ bool uaR = itemR.XmlType == null || itemR.XmlType == ua;
+ bool bothUA = uaL && uaR;
+ XPathAtomicValue avL =
+ (uaL) ?
+ bothUA ? new XPathAtomicValue (itemL.Value, str) :
+ new XPathAtomicValue (itemL.Value, itemR.XmlType) :
+ Atomize (itemL);
+ XPathAtomicValue avR =
+ uaR ?
+ bothUA ? new XPathAtomicValue (itemR.Value, str) :
+ new XPathAtomicValue (itemR.Value, itemL.XmlType) :
+ Atomize (itemR);
+
+ switch (Operation) {
+ // FIXME: it is curious but currently gmcs requires full typename.
+ case Mono.Xml.XPath2.ComparisonOperator.ValueEQ:
+ case Mono.Xml.XPath2.ComparisonOperator.GeneralEQ:
+ return XQueryComparisonOperator.ValueEQ (avL, avR);
+ case Mono.Xml.XPath2.ComparisonOperator.ValueNE:
+ case Mono.Xml.XPath2.ComparisonOperator.GeneralNE:
+ return XQueryComparisonOperator.ValueNE (avL, avR);
+ case Mono.Xml.XPath2.ComparisonOperator.ValueLT:
+ case Mono.Xml.XPath2.ComparisonOperator.GeneralLT:
+ return XQueryComparisonOperator.ValueLT (avL, avR);
+ case Mono.Xml.XPath2.ComparisonOperator.ValueLE:
+ case Mono.Xml.XPath2.ComparisonOperator.GeneralLE:
+ return XQueryComparisonOperator.ValueLE (avL, avR);
+ case Mono.Xml.XPath2.ComparisonOperator.ValueGT:
+ case Mono.Xml.XPath2.ComparisonOperator.GeneralGT:
+ return XQueryComparisonOperator.ValueGT (avL, avR);
+ case Mono.Xml.XPath2.ComparisonOperator.ValueGE:
+ case Mono.Xml.XPath2.ComparisonOperator.GeneralGE:
+ return XQueryComparisonOperator.ValueGE (avL, avR);
+ }
+ return false; // should not happen
+ }
+#endregion
+ }
+
+ public enum ComparisonOperator {
+ ValueEQ,
+ ValueNE,
+ ValueLT,
+ ValueLE,
+ ValueGT,
+ ValueGE,
+ GeneralEQ,
+ GeneralNE,
+ GeneralLT,
+ GeneralLE,
+ GeneralGT,
+ GeneralGE,
+ NodeIs,
+ NodeFWD,
+ NodeBWD
+ }
+
+ // Range
+
+ internal class RangeExpr : BinaryOperationExpr
+ {
+ public RangeExpr (ExprSingle left, ExprSingle right)
+ : base (left, right)
+ {
+ }
+
+#region CompileAndEvaluate
+ internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
+ {
+ Left = Left.Compile (compiler);
+ Right = Right.Compile (compiler);
+ return this;
+ }
+
+ public override SequenceType StaticType {
+ get { return SequenceType.IntegerList; }
+ }
+
+ public override XPathSequence Evaluate (XPathSequence iter)
+ {
+ int start = Left.EvaluateAsInt (iter);
+ int end = Right.EvaluateAsInt (iter);
+ return new IntegerRangeIterator (iter.Context, start, end);
+ }
+
+ public override void Serialize (XPathSequence iter)
+ {
+ int start = Left.EvaluateAsInt (iter);
+ int end = Right.EvaluateAsInt (iter);
+ for (int i = start; i <= end; i++) {
+ iter.Context.Writer.WriteValue (i);
+ if (i < end)
+ iter.Context.Writer.WriteWhitespace (" ");
+ }
+ }
+#endregion
+ }
+
+ // arithmetic operation expr
+
+ public enum ArithmeticOperator {
+ Add,
+ Sub,
+ Mul,
+ Div,
+ IDiv,
+ IMod
+ }
+
+ internal class ArithmeticOperationExpr : BinaryOperationExpr
+ {
+ public ArithmeticOperationExpr (ExprSingle left, ExprSingle right, ArithmeticOperator oper)
+ : base (left, right)
+ {
+ this.oper = oper;
+ }
+
+ ArithmeticOperator oper;
+
+ public ArithmeticOperator Operation {
+ get { return oper; }
+ }
+
+#region CompileAndEvaluate
+ internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
+ {
+ Left = Left.Compile (compiler);
+ Right = Right.Compile (compiler);
+ return this;
+ }
+
+ // FIXME: It can be optimized by comparing l/r value types.
+ public override SequenceType StaticType {
+ get { return SequenceType.AnyType; }
+ }
+
+ public override XPathSequence Evaluate (XPathSequence iter)
+ {
+ XPathSequence lseq = Left.Evaluate (iter);
+ if (!lseq.MoveNext ())
+ return new XPathEmptySequence (iter.Context);
+ XPathSequence rseq = Right.Evaluate (iter);
+ if (!rseq.MoveNext ())
+ return new XPathEmptySequence (iter.Context);
+ XPathAtomicValue lvalue = Atomize (lseq.Current);
+ XPathAtomicValue rvalue = Atomize (rseq.Current);
+ if (lseq.MoveNext ())
+ throw new XmlQueryException ("XP0006: Left operand resulted in an sequence that contains more than one item.");
+ if (rseq.MoveNext ())
+ throw new XmlQueryException ("XP0006: Left operand resulted in an sequence that contains more than one item.");
+
+ // FIXME: handle "untypedAtomic to xs:double" casting
+
+ return new SingleItemIterator (Compute (lvalue, rvalue), iter.Context);
+ }
+
+ private XPathAtomicValue Compute (XPathAtomicValue lvalue, XPathAtomicValue rvalue)
+ {
+ switch (Operation) {
+ case ArithmeticOperator.Add:
+ return XQueryArithmeticOperator.Add (lvalue, rvalue);
+ case ArithmeticOperator.Sub:
+ return XQueryArithmeticOperator.Subtract (lvalue, rvalue);
+ case ArithmeticOperator.Mul:
+ return XQueryArithmeticOperator.Multiply (lvalue, rvalue);
+ case ArithmeticOperator.Div:
+ return XQueryArithmeticOperator.Divide (lvalue, rvalue);
+ case ArithmeticOperator.IDiv:
+ return XQueryArithmeticOperator.IntDivide (lvalue, rvalue);
+ case ArithmeticOperator.IMod:
+ return XQueryArithmeticOperator.Remainder (lvalue, rvalue);
+ default:
+ throw new SystemException ("XQuery internal error: should not happen.");
+ }
+ }
+#endregion
+ }
+
+ internal class MinusExpr : ExprSingle
+ {
+ public MinusExpr (ExprSingle expr)
+ {
+ this.expr = expr;
+ }
+
+ ExprSingle expr;
+
+ public ExprSingle Expr {
+ get { return expr; }
+ set { expr = value; }
+ }
+
+ internal override void CheckReference (XQueryASTCompiler compiler)
+ {
+ expr.CheckReference (compiler);
+ }
+
+#region CompileAndEvaluate
+ internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
+ {
+ return new ArithmeticOperationExpr (new DecimalLiteralExpr (-1), Expr, ArithmeticOperator.Mul).Compile (compiler);
+ }
+
+ public override SequenceType StaticType {
+ get { return Expr.StaticType; }
+ }
+
+ public override XPathSequence Evaluate (XPathSequence iter)
+ {
+ throw new SystemException ("XQuery internal error: should not happen.");
+ }
+#endregion
+ }
+
+ // aggregation expr
+
+ public enum AggregationType {
+ Union,
+ Intersect,
+ Except
+ }
+
+ internal class GroupExpr : BinaryOperationExpr
+ {
+ public GroupExpr (ExprSingle left, ExprSingle right, AggregationType aggrType)
+ : base (left, right)
+ {
+ this.aggrType = aggrType;
+ }
+
+ AggregationType aggrType;
+
+ public AggregationType AggregationType {
+ get { return aggrType; }
+ }
+
+#region CompileAndEvaluate
+ internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
+ {
+ Left = Left.Compile (compiler);
+ Right = Right.Compile (compiler);
+ return this;
+ }
+
+ // FIXME: It can be optimized by comparing l/r value types.
+ public override SequenceType StaticType {
+ get { return SequenceType.AnyType; }
+ }
+
+ // only applicable against node-sets
+ public override XPathSequence Evaluate (XPathSequence iter)
+ {
+ return new GroupIterator (iter, this);
+ }
+#endregion
+ }
+
+ // validate expr
+
+ internal class ValidateExpr : ExprSingle
+ {
+ XmlSchemaContentProcessing schemaMode;
+ ExprSequence expr;
+
+ public ValidateExpr (XmlSchemaContentProcessing schemaMode, ExprSequence expr)
+ {
+ this.schemaMode = schemaMode;
+ this.expr = expr;
+ }
+
+ public ExprSequence Expr {
+ get { return expr; }
+ }
+
+ public XmlSchemaContentProcessing SchemaMode {
+ get { return schemaMode; }
+ }
+
+ internal override void CheckReference (XQueryASTCompiler compiler)
+ {
+ expr.CheckReference (compiler);
+ }
+
+#region CompileAndEvaluate
+ internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
+ {
+ for (int i = 0; i < expr.Count; i++)
+ expr [i] = expr [i].Compile (compiler);
+ return this;
+ }
+
+ public override SequenceType StaticType {
+ get { return SequenceType.AnyType; }
+ }
+
+ public override XPathSequence Evaluate (XPathSequence iter)
+ {
+ // TBD (see 3.13).
+ throw new NotImplementedException ();
+ }
+#endregion
+ }
+
+ // Path expr
+
+ internal abstract class PathExpr : ExprSingle
+ {
+ }
+
+ // '/'
+ internal class PathRootExpr : PathExpr
+ {
+ public PathRootExpr ()
+ {
+ }
+
+ internal override void CheckReference (XQueryASTCompiler compiler)
+ {
+ }
+
+#region CompileAndEvaluate
+ internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
+ {
+ return this;
+ }
+
+ public override SequenceType StaticType {
+ get { return SequenceType.Document; }
+ }
+
+ public override XPathSequence Evaluate (XPathSequence iter)
+ {
+ XPathNavigator nav = iter.Context.CurrentItem as XPathNavigator;
+ if (nav == null)
+ throw new XmlQueryException ("Context item is not a node when evaluating expression '/'.");
+ nav = nav.Clone ();
+ nav.MoveToRoot ();
+ return new SingleItemIterator (nav, iter.Context);
+ }
+#endregion
+ }
+
+ internal abstract class PathStepExpr : PathExpr
+ {
+ ExprSingle first;
+ ExprSingle next;
+
+ public PathStepExpr (ExprSingle first, ExprSingle next)
+ {
+ this.first = first;
+ this.next = next;
+ }
+
+ public ExprSingle First {
+ get { return first; }
+ set { first = value; }
+ }
+
+ public ExprSingle Next {
+ get { return next; }
+ set { next = value; }
+ }
+
+ internal override void CheckReference (XQueryASTCompiler compiler)
+ {
+ first.CheckReference (compiler);
+ next.CheckReference (compiler);
+ }
+
+ internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
+ {
+ first = first.Compile (compiler);
+ next = next.Compile (compiler);
+ return this;
+ }
+
+ }
+
+ // 'foo/bar'
+ internal class PathSlashExpr : PathStepExpr
+ {
+ public PathSlashExpr (ExprSingle first, ExprSingle next)
+ : base (first, next)
+ {
+ }
+
+#region CompileAndEvaluate
+ // FIXME: It can be optimized by comparing l/r value types.
+ public override SequenceType StaticType {
+ get { return SequenceType.Node; }
+ }
+
+ public override XPathSequence Evaluate (XPathSequence iter)
+ {
+ return new PathStepIterator (First.Evaluate (iter), this);
+ }
+#endregion
+ }
+
+ // 'foo//bar'
+ internal class PathSlash2Expr : PathStepExpr
+ {
+ public PathSlash2Expr (ExprSingle first, ExprSingle next)
+ : base (first, next)
+ {
+ }
+
+#region CompileAndEvaluate
+ // FIXME: It can be optimized by comparing l/r value types.
+ public override SequenceType StaticType {
+ get { return SequenceType.Node; }
+ }
+
+ public override XPathSequence Evaluate (XPathSequence iter)
+ {
+ XPathSequence seq = First.Evaluate (iter);
+ if (!seq.MoveNext ())
+ return new XPathEmptySequence (iter.Context);
+ return new PathStepIterator (
+ new DescendantOrSelfIterator (seq.Current as XPathNavigator, seq.Context), this);
+ }
+#endregion
+ }
+
+ internal class AxisStepExpr : PathExpr
+ {
+ public AxisStepExpr (XPathAxis axis, XPath2NodeTest test)
+ {
+ this.axis = axis;
+ if (test == null)
+ nameTest = XmlQualifiedName.Empty;
+ else {
+ if (test.NameTest != null)
+ this.nameTest = test.NameTest;
+ else
+ this.kindTest = test.KindTest;
+ }
+ }
+
+ XPathAxis axis;
+ XmlQualifiedName nameTest;
+ KindTest kindTest;
+
+ public XPathAxis Axis {
+ get { return axis; }
+ }
+
+ public XmlQualifiedName NameTest {
+ get { return nameTest; }
+ set { nameTest = value; }
+ }
+
+ public KindTest KindTest {
+ get { return kindTest; }
+ set { kindTest = value; }
+ }
+
+ internal override void CheckReference (XQueryASTCompiler compiler)
+ {
+ if (KindTest != null)
+ KindTest.CheckReference (compiler);
+ }
+
+#region CompileAndEvaluate
+ internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
+ {
+ if (KindTest != null)
+ KindTest.Compile (compiler);
+ return this;
+ }
+
+ public override SequenceType StaticType {
+ get {
+ switch (Axis.AxisType) {
+ case XPathAxisType.Attribute:
+ return SequenceType.Attribute;
+ case XPathAxisType.Namespace:
+ return SequenceType.Namespace;
+ }
+ // FIXME: we can more filtering by KindTest
+ return SequenceType.Node;
+ }
+ }
+
+ public override XPathSequence Evaluate (XPathSequence iter)
+ {
+ XQueryContext ctx = iter.Context;
+
+ if (iter.Position == 0) {
+ iter = iter.Clone ();
+ if (!iter.MoveNext ())
+ return new XPathEmptySequence (iter.Context);
+ }
+
+ XPathNavigator nav = iter.Current as XPathNavigator;
+ if (nav == null)
+ throw new XmlQueryException ("Node set is expected.");
+
+ NodeIterator argIter = null;
+
+ switch (Axis.AxisType) {
+ case XPathAxisType.Child:
+ argIter = new ChildIterator (nav, ctx); break;
+ case XPathAxisType.Descendant:
+ argIter = new DescendantIterator (nav, ctx); break;
+ case XPathAxisType.Attribute:
+ argIter = new AttributeIterator (nav, ctx); break;
+ case XPathAxisType.Self:
+ argIter = new SelfIterator (nav, ctx); break;
+ case XPathAxisType.DescendantOrSelf:
+ argIter = new DescendantOrSelfIterator (nav, ctx); break;
+ case XPathAxisType.FollowingSibling:
+ argIter = new FollowingSiblingIterator (nav, ctx); break;
+ case XPathAxisType.Following:
+ argIter = new FollowingIterator (nav, ctx); break;
+ case XPathAxisType.Parent:
+ argIter = new ParentIterator (nav, ctx); break;
+ case XPathAxisType.Ancestor:
+ argIter = new AncestorIterator (nav, ctx); break;
+ case XPathAxisType.PrecedingSibling:
+ argIter = new PrecedingSiblingIterator (nav, ctx); break;
+ case XPathAxisType.Preceding:
+ argIter = new PrecedingIterator (nav, ctx); break;
+ case XPathAxisType.AncestorOrSelf:
+ argIter = new AncestorOrSelfIterator (nav, ctx); break;
+ case XPathAxisType.Namespace: // only applicable under XPath 2.0: not XQuery 1.0
+ argIter = new NamespaceIterator (nav, ctx); break;
+ }
+ return new AxisIterator (argIter, this);
+ }
+
+ internal bool Matches (XPathNavigator nav)
+ {
+ if (nameTest != null)
+ return nameTest == XmlQualifiedName.Empty ||
+ ((nameTest.Name == nav.LocalName || nameTest.Name == "*") &&
+ (nameTest.Namespace == nav.NamespaceURI || nameTest.Namespace == "*"));
+ else
+ return kindTest.Matches (nav);
+ }
+#endregion
+ }
+
+ internal class FilterStepExpr : PathExpr
+ {
+ public FilterStepExpr (ExprSingle expr, ExprSequence predicate)
+ {
+ this.expr = expr;
+ this.predicate = predicate;
+ }
+
+ ExprSingle expr;
+ ExprSequence predicate;
+
+ public ExprSingle Expr {
+ get { return expr; }
+ set { expr = value; }
+ }
+
+ public ExprSequence Predicate {
+ get { return predicate; }
+ }
+
+ internal override void CheckReference (XQueryASTCompiler compiler)
+ {
+ expr.CheckReference (compiler);
+ predicate.CheckReference (compiler);
+ }
+
+#region CompileAndEvaluate
+ internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
+ {
+ Expr = Expr.Compile (compiler);
+ for (int i = 0; i < predicate.Count; i++)
+ predicate [i] = predicate [i].Compile (compiler);
+ return this;
+ }
+
+ public override SequenceType StaticType {
+ get { return Expr.StaticType; }
+ }
+
+ public override XPathSequence Evaluate (XPathSequence iter)
+ {
+ return new FilteredIterator (iter, this);
+ }
+#endregion
+ }
+
+/*
+ // predicates == exprsequence list == list of list of exprsingle
+ internal class PredicateList : CollectionBase
+ {
+ public void Add (ExprSequence expr)
+ {
+ List.Add (expr);
+ }
+
+ public void Insert (int pos, ExprSequence expr)
+ {
+ List.Insert (pos, expr);
+ }
+
+ public ExprSequence this [int i] {
+ get { return (ExprSequence) List [i]; }
+ }
+ }
+*/
+
+ internal class XPath2NodeTest
+ {
+ public XPath2NodeTest (XmlQualifiedName nameTest)
+ {
+ this.NameTest = nameTest;
+ }
+
+ public XPath2NodeTest (KindTest kindTest)
+ {
+ this.KindTest = kindTest;
+ }
+
+ public XmlQualifiedName NameTest;
+
+ public KindTest KindTest;
+ }
+
+ internal class EnclosedExpr : ExprSingle
+ {
+ ExprSequence expr;
+
+ public EnclosedExpr (ExprSequence expr)
+ {
+ this.expr = expr;
+ }
+
+ public ExprSequence Expr {
+ get { return expr; }
+ }
+
+ internal override void CheckReference (XQueryASTCompiler compiler)
+ {
+ expr.CheckReference (compiler);
+ }
+
+#region CompileAndEvaluate
+ internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
+ {
+ if (Expr.Count == 1)
+ return Expr [0].Compile (compiler);
+ for (int i = 0; i < Expr.Count; i++)
+ Expr [i] = Expr [i].Compile (compiler);
+ return this;
+ }
+
+ // FIXME: can be optimized by checking all items in Expr
+ public override SequenceType StaticType {
+ get { return SequenceType.AnyType; }
+ }
+
+ public override XPathSequence Evaluate (XPathSequence iter)
+ {
+ return new ExprSequenceIterator (iter, Expr);
+ }
+#endregion
+ }
+
+ // PrimaryExpr
+
+ internal abstract class PrimaryExpr : ExprSingle
+ {
+ internal override void CheckReference (XQueryASTCompiler compiler)
+ {
+ }
+
+#region CompileAndEvaluate
+ internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
+ {
+ return this;
+ }
+
+ public override XPathSequence Evaluate (XPathSequence iter)
+ {
+ return new SingleItemIterator (EvaluateAsAtomic (iter), iter.Context);
+ }
+#endregion
+ }
+
+ internal class StringLiteralExpr : PrimaryExpr
+ {
+ string literal;
+
+ public StringLiteralExpr (string literal)
+ {
+ this.literal = literal;
+ }
+
+ public string Literal {
+ get { return literal; }
+ }
+
+#region CompileAndEvaluate
+ XmlSchemaSimpleType stringType = XmlSchemaType.GetBuiltInSimpleType (new XmlQualifiedName ("string", XmlSchema.Namespace));
+
+ public override SequenceType StaticType {
+ get { return SequenceType.AtomicString; }
+ }
+
+ public override string EvaluateAsString (XPathSequence iter)
+ {
+ return Literal;
+ }
+
+ public override XPathAtomicValue EvaluateAsAtomic (XPathSequence iter)
+ {
+ return new XPathAtomicValue (Literal, stringType);
+ }
+#endregion
+ }
+
+ internal class DecimalLiteralExpr : PrimaryExpr
+ {
+ decimal value;
+
+ public DecimalLiteralExpr (decimal value)
+ {
+ this.value = value;
+ }
+
+ public decimal Value {
+ get { return value; }
+ }
+
+#region CompileAndEvaluate
+ XmlSchemaSimpleType decimalType = XmlSchemaType.GetBuiltInSimpleType (new XmlQualifiedName ("decimal", XmlSchema.Namespace));
+
+ public override SequenceType StaticType {
+ get { return SequenceType.Decimal; }
+ }
+
+ public override XPathAtomicValue EvaluateAsAtomic (XPathSequence iter)
+ {
+ return new XPathAtomicValue (Value, decimalType);
+ }
+#endregion
+ }
+
+ internal class DoubleLiteralExpr : PrimaryExpr
+ {
+ double value;
+
+ public DoubleLiteralExpr (double value)
+ {
+ this.value = value;
+ }
+
+ public double Value {
+ get { return value; }
+ }
+
+#region CompileAndEvaluate
+ XmlSchemaSimpleType doubleType = XmlSchemaType.GetBuiltInSimpleType (new XmlQualifiedName ("double", XmlSchema.Namespace));
+
+ public override SequenceType StaticType {
+ get { return SequenceType.Double; }
+ }
+
+ public override XPathAtomicValue EvaluateAsAtomic (XPathSequence iter)
+ {
+ return new XPathAtomicValue (Value, doubleType);
+ }
+#endregion
+ }
+
+ internal class VariableReferenceExpr : PrimaryExpr
+ {
+ XmlQualifiedName varName;
+
+ public VariableReferenceExpr (XmlQualifiedName varName)
+ {
+ this.varName = varName;
+ }
+
+ public XmlQualifiedName VariableName {
+ get { return varName; }
+ }
+
+ // FIXME: variable name must be stacked in any area
+ // whereever variables are defined.
+ internal override void CheckReference (XQueryASTCompiler compiler)
+ {
+ compiler.CheckVariableName (varName);
+ }
+
+#region CompileAndEvaluate
+ internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
+ {
+ // FIXME: try to resolve static context variable and return the actual value expression
+ return this;
+ }
+
+ public override SequenceType StaticType {
+ get { return SequenceType.AnyType; }
+ }
+
+ public override XPathSequence Evaluate (XPathSequence iter)
+ {
+ XPathSequence variable = iter.Context.ResolveVariable (VariableName);
+ // FIXME: if Evaluate() accepts XPathSequence, then XPathSequence must be public class (to make IXPath2Variable public).
+ return variable;
+ }
+#endregion
+ }
+
+ internal class ParenthesizedExpr : PrimaryExpr
+ {
+ ExprSequence expr;
+
+ public ParenthesizedExpr (ExprSequence expr)
+ {
+ if (expr == null)
+ expr = new ExprSequence ();
+ this.expr = expr;
+ }
+
+ ExprSequence Expr {
+ get { return expr; }
+ }
+
+#region CompileAndEvaluate
+ internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
+ {
+ if (Expr.Count == 1)
+ return Expr [0].Compile (compiler);
+ for (int i = 0; i < Expr.Count; i++)
+ Expr [i] = Expr [i].Compile (compiler);
+ return this;
+ }
+
+ // FIXME: can be optimized by checking all items in Expr
+ public override SequenceType StaticType {
+ get { return SequenceType.AnyType; }
+ }
+
+ public override XPathSequence Evaluate (XPathSequence iter)
+ {
+ switch (Expr.Count) {
+ case 0:
+ return new XPathEmptySequence (iter.Context);
+ case 1:
+ return Expr [0].Evaluate (iter);
+ default:
+ return new ExprSequenceIterator (iter, Expr);
+ }
+ }
+#endregion
+ }
+
+ // "."
+ internal class ContextItemExpr : PrimaryExpr
+ {
+ public ContextItemExpr ()
+ {
+ }
+
+#region CompileAndEvaluate
+ internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
+ {
+ return this;
+ }
+
+ public override SequenceType StaticType {
+ get { return SequenceType.AnyType; }
+ }
+
+ public override XPathSequence Evaluate (XPathSequence iter)
+ {
+ return new SingleItemIterator (iter.Context.CurrentItem, iter.Context);
+ }
+#endregion
+ }
+
+ internal abstract class FunctionCallExprBase : PrimaryExpr
+ {
+ XmlQualifiedName name;
+ ExprSequence args;
+
+ public FunctionCallExprBase (XmlQualifiedName name, ExprSequence args)
+ {
+ if (args == null)
+ throw new ArgumentNullException (String.Format ("Function argument expressions for {0} is null.", name));
+ this.name = name;
+ this.args = args;
+ }
+
+ public XmlQualifiedName Name {
+ get { return name; }
+ }
+
+ public ExprSequence Args {
+ get { return args; }
+ }
+
+ internal override void CheckReference (XQueryASTCompiler compiler)
+ {
+ compiler.CheckFunctionName (name);
+ }
+
+#region CompileAndEvaluate
+ /*
+ internal static DefaultFunctionCall Create (
+ XmlQualifiedName name,
+ ExprSingle [] args,
+ XQueryStaticContext ctx)
+ {
+ switch (name.Namespace) {
+ case XQueryFunction.Namespace:
+ switch (name.Name) {
+ case "node-name":
+ return new FnNodeNameCall (ctx, args);
+ case "nilled":
+ return new FnNilledCall (ctx, args);
+ case "string":
+ return new FnStringCall (ctx, args);
+ case "data":
+ return new FnDataCall (ctx, args);
+ case "base-uri":
+ return new FnBaseUriCall (ctx, args);
+ case "document-uri":
+ return new FnDocumentUriCall (ctx, args);
+ case "error":
+ return new FnErrorCall (ctx, args);
+ case "trace":
+ return new FnTraceCall (ctx, args);
+ case "abs":
+ return new FnAbsCall (ctx, args);
+ case "ceiling":
+ return new FnCeilingCall (ctx, args);
+ case "floor":
+ return new FnFloorCall (ctx, args);
+ case "round":
+ return new FnRoundCall (ctx, args);
+ case "round-half-to-even":
+ return new FnRoundHalfToEvenCall (ctx, args);
+ case "codepoints-to-string":
+ return new FnCodepointsToStringCall (ctx, args);
+ case "string-to-codepoints":
+ return new FnStringCallToCodepointsCall (ctx, args);
+ }
+ goto default;
+ case InternalPool.XdtNamespace:
+ case XmlSchema.Namespace:
+ XmlSchemaType type = XmlSchemaType.GetBuiltInSimpleType (name);
+ if (type != null)
+ return new AtomicConstructorCall (ctx, SequenceType.Create (type, Occurence.One), args);
+ type = XmlSchemaType.GetBuiltInComplexType (name);
+ if (type == null)
+ goto default;
+ return null;
+ default:
+ XQueryFunction func = ctx.CompileContext.InEffectFunctions [name];
+ if (func != null)
+ return new CustomFunctionCallExpression (ctx, args, func);
+ return null;
+ }
+ }
+ */
+
+ internal void CheckArguments (XQueryASTCompiler compiler)
+ {
+ if (args.Count < MinArgs || args.Count > MaxArgs)
+ // FIXME: add more info
+ throw new XmlQueryCompileException (String.Format ("{0} is invalid for the number of {1} function argument. MinArgs = {2}, MaxArgs = {3}.", args.Count, name, MinArgs, MaxArgs));
+ }
+
+ public abstract int MinArgs { get; }
+ public abstract int MaxArgs { get; }
+#endregion
+ }
+
+ internal class FunctionCallExpr : FunctionCallExprBase
+ {
+ public FunctionCallExpr (XmlQualifiedName name, ExprSequence args)
+ : base (name, args)
+ {
+ }
+
+ XQueryFunction function;
+
+ public XQueryFunction Function {
+ get { return function; }
+ }
+
+#region CompileAndEvaluate
+ internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
+ {
+ // resolve function
+ function = compiler.ResolveFunction (Name);
+ CheckArguments (compiler);
+ for (int i = 0; i < Args.Count; i++)
+ Args [i] = Args [i].Compile (compiler);
+ return this;
+ }
+
+ public override int MinArgs {
+ get { return function.MinArgs; }
+ }
+
+ public override int MaxArgs {
+ get { return function.MaxArgs; }
+ }
+
+ public override SequenceType StaticType {
+ get { return function.ReturnType; }
+ }
+
+ public override XPathSequence Evaluate (XPathSequence iter)
+ {
+ return Function.Evaluate (iter, Args);
+ }
+
+ // FIXME: add all overrides that delegates to XQueryFunction
+#endregion
+ }
+
+/*
+#region CompileAndEvaluate
+
+ // It is instantiated per function call expression.
+ // (e.g. the example below contains 4 FunctionCallExpression instances:
+ // "replace(node-name (node-before(/*)), 'foo', node-name($var))"
+ internal class CustomFunctionCallExpr : FunctionCallExprBase
+ {
+ public CustomFunctionCallExpr (ExprSequence args, XQueryFunction function)
+ : base (function.Name, args)
+ {
+ this.function = function;
+ }
+
+ XQueryFunction function;
+
+ public XQueryFunction Function {
+ get { return function; }
+ }
+
+ public override int MinArgs {
+ get { return function.MinArgs; }
+ }
+
+ public override int MaxArgs {
+ get { return function.MaxArgs; }
+ }
+
+ public override SequenceType StaticType {
+ get { return function.ReturnType; }
+ }
+
+ internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
+ {
+ CheckArguments (compiler);
+ for (int i = 0; i < Args.Count; i++)
+ Args [i] = Args [i].Compile (compiler);
+ return this;
+ }
+
+ public override XPathSequence Evaluate (XPathSequence iter)
+ {
+ return Function.Evaluate (iter, Args);
+ }
+
+ // FIXME: add all overrides that delegates to XQueryFunction
+ }
+#endregion
+*/
+
+ // Ordered / Unordered
+ internal class OrderSpecifiedExpr : ExprSingle
+ {
+ bool ordered;
+ ExprSequence expr;
+
+ public OrderSpecifiedExpr (ExprSequence expr, bool ordered)
+ {
+ this.ordered = ordered;
+ this.expr = expr;
+ }
+
+ public ExprSequence Expr {
+ get { return expr; }
+ }
+
+ public bool Ordered {
+ get { return ordered; }
+ }
+
+ internal override void CheckReference (XQueryASTCompiler compiler)
+ {
+ expr.CheckReference (compiler);
+ }
+
+#region CompileAndEvaluate
+ public override SequenceType StaticType {
+ // FIXME: could be optimized by checking all the expressions
+ get { return SequenceType.AnyType; }
+ }
+
+ public override bool RequireSorting {
+ get { return Ordered; }
+ }
+
+ internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
+ {
+ for (int i = 0; i < Expr.Count; i++)
+ Expr [i] = Expr [i].Compile (compiler);
+ return this;
+ }
+
+ public override XPathSequence Evaluate (XPathSequence iter)
+ {
+ throw new NotImplementedException ();
+ }
+#endregion
+ }
+}
+
+#endif
diff --git a/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XPathSequence.cs b/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XPathSequence.cs
new file mode 100755
index 00000000000..602e09d6aa1
--- /dev/null
+++ b/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XPathSequence.cs
@@ -0,0 +1,1779 @@
+//
+// XPathSequence.cs - represents XPath sequence iterator
+//
+// Author:
+// Atsushi Enomoto <atsushi@ximian.com>
+//
+//
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+#if NET_2_0
+using System;
+using System.Collections;
+using System.Globalization;
+using System.Xml;
+using System.Xml.Schema;
+using System.Xml.Query;
+using System.Xml.XPath;
+
+namespace Mono.Xml.XPath2
+{
+ public abstract class XPathSequence : IEnumerable, ICloneable
+ {
+ XQueryContext ctx;
+ int countCache = -1;
+ int position = 0;
+
+ internal XPathSequence (XQueryContext ctx)
+ {
+ this.ctx = ctx;
+ }
+
+ internal XPathSequence (XPathSequence original)
+ {
+ ctx = original.ctx;
+ position = original.position;
+ }
+
+ internal XQueryContext Context {
+// get { return ctx; }
+ get { return ctx.ContextManager.CurrentContext; }
+ }
+
+ public virtual int Count {
+ get {
+ if (countCache >= 0)
+ return countCache;
+ XPathSequence clone = Clone ();
+ while (clone.MoveNext ())
+ ;
+ countCache = clone.Position;
+ return countCache;
+ }
+ }
+
+ public XPathItem Current {
+ get {
+ if (Position == 0)
+ throw new InvalidOperationException ("XQuery internal error (should not happen)");
+ return CurrentCore;
+ }
+ }
+
+ public abstract XPathItem CurrentCore { get; }
+
+ // Returns 0 if not started, otherwise returns XPath positional integer.
+ public virtual int Position {
+ get { return position; }
+ }
+
+ public virtual bool MoveNext ()
+ {
+ if (!MoveNextCore ())
+ return false;
+ position++;
+ return true;
+ }
+
+ protected abstract bool MoveNextCore ();
+
+ public abstract XPathSequence Clone ();
+
+ object ICloneable.Clone ()
+ {
+ return this.Clone ();
+ }
+
+ public virtual IEnumerator GetEnumerator ()
+ {
+ while (MoveNext ())
+ yield return CurrentCore;
+ }
+
+ }
+
+ // empty iterator (still required since it contains XQueryContext)
+ class XPathEmptySequence : XPathSequence
+ {
+ internal XPathEmptySequence (XQueryContext ctx)
+ : base (ctx)
+ {
+ }
+
+ public override int Count {
+ get { return 0; }
+ }
+
+ protected override bool MoveNextCore ()
+ {
+ return false;
+ }
+
+ public override XPathItem CurrentCore {
+ get { throw new InvalidOperationException ("Should not happen. In XPathEmptySequence.Current."); }
+ }
+
+ // Don't return clone. It's waste of resource.
+ public override XPathSequence Clone ()
+ {
+ return this;
+ }
+ }
+
+ // single item iterator
+
+ internal class SingleItemIterator : XPathSequence
+ {
+ XPathItem item;
+ XPathItem current;
+
+ // for XQuery execution start point
+ internal SingleItemIterator (XPathItem item, XQueryContext ctx)
+ : base (ctx)
+ {
+ this.item = item;
+ }
+
+ private SingleItemIterator (SingleItemIterator other)
+ : base (other)
+ {
+ this.item = other.item;
+ this.current = other.current;
+ }
+
+ public override XPathSequence Clone ()
+ {
+ return new SingleItemIterator (this);
+ }
+
+ protected override bool MoveNextCore ()
+ {
+ if (current == null) {
+ current = item;
+ return true;
+ }
+ return false;
+ }
+
+ public override XPathItem CurrentCore {
+ get {
+ return current;
+ }
+ }
+ }
+
+ // RangeExpr iterator
+
+ internal class IntegerRangeIterator : XPathSequence
+ {
+ static XmlSchemaSimpleType intType = XmlSchemaType.GetBuiltInSimpleType (new XmlQualifiedName ("int", XmlSchema.Namespace));
+
+ int start;
+ int end;
+ int next;
+ XPathItem current;
+
+ public IntegerRangeIterator (XQueryContext ctx, int start, int end)
+ : base (ctx)
+ {
+ this.start = start;
+ this.end = end;
+ }
+
+ private IntegerRangeIterator (IntegerRangeIterator other)
+ : base (other)
+ {
+ this.start = other.start;
+ this.end = other.end;
+ this.next = other.next;
+ this.current = other.current;
+ }
+
+ public override XPathSequence Clone ()
+ {
+ return new IntegerRangeIterator (this);
+ }
+
+ protected override bool MoveNextCore ()
+ {
+ if (current == null)
+ next = start;
+ if (next > end)
+ return false;
+ current = new XPathAtomicValue (next++, intType);
+ return true;
+ }
+
+ public override XPathItem CurrentCore {
+ get {
+ return current;
+ }
+ }
+ }
+
+ // Slash iterator
+ // <copy original='System.Xml.XPath/Iterator.cs,
+ // System.Xml.XPath/XPathComparer.cs'>
+ internal class PathStepIterator : XPathSequence
+ {
+ XPathSequence left;
+ XPathSequence right;
+ PathStepExpr step;
+ ArrayList nodeStore;
+ SortedList storedIterators;
+ bool finished;
+ XPathSequence nextRight;
+
+ public PathStepIterator (XPathSequence iter, PathStepExpr source)
+ : base (iter.Context)
+ {
+ left = iter;
+ step = source;
+ }
+
+ private PathStepIterator (PathStepIterator other)
+ : base (other)
+ {
+ left = other.left.Clone ();
+ step = other.step;
+ if (other.right != null)
+ right = other.right.Clone ();
+ if (other.nodeStore != null)
+ nodeStore = (ArrayList) other.nodeStore.Clone ();
+ if (other.storedIterators != null)
+ storedIterators = (SortedList) other.storedIterators.Clone ();
+ if (other.nextRight != null)
+ nextRight = other.nextRight.Clone ();
+ }
+
+ public override XPathSequence Clone ()
+ {
+ return new PathStepIterator (this);
+ }
+
+ protected override bool MoveNextCore ()
+ {
+ if (finished)
+ return false;
+ if (step.RequireSorting) {
+ // Mainly '//' ('/descendant-or-self::node()/')
+ if (nodeStore == null) {
+ CollectResults ();
+ if (nodeStore.Count == 0) {
+ finished = true;
+ return false;
+ } else
+ // Initially it must not go to
+ // the while loop below
+ // (.Position -1 is -1).
+ return true;
+ }
+ if (nodeStore.Count == Position) {
+ finished = true;
+ return false;
+ }
+ while (nodeStore.Count > Position) {
+ if (((XPathNavigator) nodeStore [Position]).ComparePosition (
+ (XPathNavigator) nodeStore [Position - 1]) == XmlNodeOrder.Same)
+ nodeStore.RemoveAt (Position);
+ else
+ break;
+ }
+
+ return true;
+ } else { // Sorting not required
+ if (right == null) { // First time
+ if (!left.MoveNext ())
+ return false;
+ right = step.Next.Evaluate (left);
+ storedIterators = new SortedList (XPathSequenceComparer.Instance);
+ }
+
+ while (true) {
+ while (!right.MoveNext ()) {
+ if (storedIterators.Count > 0) {
+ int last = storedIterators.Count - 1;
+ XPathSequence tmpIter = (XPathSequence) storedIterators.GetByIndex (last);
+ storedIterators.RemoveAt (last);
+ switch (((XPathNavigator) tmpIter.Current).ComparePosition ((XPathNavigator) right.Current)) {
+ case XmlNodeOrder.Same:
+ case XmlNodeOrder.Before:
+ right = tmpIter;
+ continue;
+ default:
+ right = tmpIter;
+ break;
+ }
+ break;
+ } else if (nextRight != null) {
+ right = nextRight;
+ nextRight = null;
+ break;
+ } else if (!left.MoveNext ()) {
+ finished = true;
+ return false;
+ }
+ else
+ right = step.Next.Evaluate (left);
+ }
+ bool loop = true;
+ while (loop) {
+ loop = false;
+ if (nextRight == null) {
+ bool noMoreNext = false;
+ while (nextRight == null || !nextRight.MoveNext ()) {
+ if(left.MoveNext ())
+ nextRight = step.Next.Evaluate (left);
+ else {
+ noMoreNext = true;
+ break;
+ }
+ }
+ if (noMoreNext)
+ nextRight = null; // FIXME: More efficient code. Maybe making noMoreNext class scope would be better.
+ }
+ if (nextRight != null) {
+ switch (((XPathNavigator) right.Current).ComparePosition ((XPathNavigator) nextRight.Current)) {
+ case XmlNodeOrder.After:
+ storedIterators.Add (storedIterators.Count, right);
+ right = nextRight;
+ nextRight = null;
+ loop = true;
+ break;
+ case XmlNodeOrder.Same:
+ if (!nextRight.MoveNext ())
+ nextRight = null;
+
+ else {
+ int last = storedIterators.Count;
+ if (last > 0) {
+ storedIterators.Add (last, nextRight);
+ nextRight = (XPathSequence) storedIterators.GetByIndex (last);
+ storedIterators.RemoveAt (last);
+ }
+ }
+
+ loop = true;
+ break;
+ }
+ }
+ }
+ return true;
+ }
+ }
+ }
+
+ private void CollectResults ()
+ {
+ if (nodeStore != null)
+ return;
+ nodeStore = new ArrayList ();
+ while (true) {
+ while (right == null || !right.MoveNext ()) {
+ if (!left.MoveNext ()) {
+ nodeStore.Sort (XPathNavigatorComparer2.Instance);
+ return;
+ }
+ right = step.Next.Evaluate (left);
+ }
+ XPathNavigator nav = (XPathNavigator) right.Current;
+ nodeStore.Add (nav);
+ }
+ }
+
+ public override XPathItem CurrentCore {
+ get {
+ if (Position <= 0) return null;
+ if (step.RequireSorting) {
+ return (XPathNavigator) nodeStore [Position - 1];
+ } else {
+ return right.Current;
+ }
+ }
+ }
+
+ public override int Count {
+ get {
+ if (nodeStore == null)
+ return base.Count;
+ else
+ return nodeStore.Count;
+ }
+ }
+
+
+ internal class XPathSequenceComparer : IComparer
+ {
+ public static XPathSequenceComparer Instance = new XPathSequenceComparer ();
+ private XPathSequenceComparer ()
+ {
+ }
+
+ public int Compare (object o1, object o2)
+ {
+ XPathSequence nav1 = o1 as XPathSequence;
+ XPathSequence nav2 = o2 as XPathSequence;
+ if (nav1 == null)
+ return -1;
+ if (nav2 == null)
+ return 1;
+ switch (((XPathNavigator) nav1.Current).ComparePosition ((XPathNavigator) nav2.Current)) {
+ case XmlNodeOrder.Same:
+ return 0;
+ case XmlNodeOrder.After:
+ return -1;
+ default:
+ return 1;
+ }
+ }
+ }
+
+ internal class XPathNavigatorComparer2 : IComparer
+ {
+ public static XPathNavigatorComparer2 Instance = new XPathNavigatorComparer2 ();
+ private XPathNavigatorComparer2 ()
+ {
+ }
+
+ public int Compare (object o1, object o2)
+ {
+ XPathNavigator nav1 = o1 as XPathNavigator;
+ XPathNavigator nav2 = o2 as XPathNavigator;
+ if (nav1 == null)
+ return -1;
+ if (nav2 == null)
+ return 1;
+ switch (nav1.ComparePosition (nav2)) {
+ case XmlNodeOrder.Same:
+ return 0;
+ case XmlNodeOrder.After:
+ return 1;
+ default:
+ return -1;
+ }
+ }
+ }
+ }
+ // </copy>
+
+ // Filter step iterator
+ internal class FilteredIterator : XPathSequence
+ {
+ XPathSequence left;
+ ExprSequence filter;
+
+ public FilteredIterator (XPathSequence iter, FilterStepExpr source)
+ : base (iter.Context)
+ {
+ left = source.Expr.Evaluate (iter);
+ filter = source.Predicate;
+ }
+
+ private FilteredIterator (FilteredIterator other)
+ : base (other)
+ {
+ left = other.left.Clone ();
+ filter = other.filter;
+ }
+
+ public override XPathSequence Clone ()
+ {
+ return new FilteredIterator (this);
+ }
+
+ protected override bool MoveNextCore ()
+ {
+ // FIXME: as for numeric predicates, it is MUCH faster
+ // when it skips apparent non-candidates, with possible
+ // method implementation "XPathSequence.SkipTo (int)".
+ // When it comes true, iteration won't be done first.
+ while (left.MoveNext ()) {
+ bool doesntPass = true;
+ // Treat as OK if any of filter expr passed.
+ // FIXME: handle numeric predicate.
+ foreach (ExprSingle single in filter) {
+ XPathAtomicValue av = single.EvaluateAsAtomic (left);
+ if (av == null)
+ continue;
+ if (SequenceType.IsNumeric (av.XmlType.TypeCode)) {
+ // numeric filter
+ if (av.ValueAsInt32 == left.Position) {
+ doesntPass = false;
+ break;
+ }
+ }
+ else if (single.EvaluateAsBoolean (left)) {
+ doesntPass = false;
+ break;
+ }
+ }
+ if (doesntPass)
+ continue;
+ return true;
+ }
+ return false;
+ }
+
+ public override XPathItem CurrentCore {
+ get { return left.Current; }
+ }
+ }
+
+ // AxisIterator
+ internal class AxisIterator : XPathSequence
+ {
+ NodeIterator iter;
+ AxisStepExpr source;
+
+ public AxisIterator (NodeIterator iter, AxisStepExpr source)
+ : base (iter.Context)
+ {
+ this.iter = iter;
+ this.source = source;
+ }
+
+ private AxisIterator (AxisIterator other)
+ : base (other)
+ {
+ iter = (NodeIterator) other.iter.Clone ();
+ source = other.source;
+ }
+
+ public override XPathSequence Clone ()
+ {
+ return new AxisIterator (this);
+ }
+
+ protected override bool MoveNextCore ()
+ {
+ while (iter.MoveNext ()) {
+ if (source.Matches (iter.Current as XPathNavigator))
+ return true;
+ }
+ return false;
+ }
+
+ public override XPathItem CurrentCore {
+ get { return iter.Current; }
+ }
+ }
+
+ internal abstract class NodeIterator : XPathSequence
+ {
+ XPathNavigator node;
+ XPathNavigator current;
+ bool emptyInput;
+
+ public NodeIterator (XPathNavigator nav, XQueryContext ctx)
+ : base (ctx)
+ {
+ this.node = nav.Clone ();
+ }
+
+ internal NodeIterator (NodeIterator other, bool cloneFlag)
+ : base (other)
+ {
+ if (other.emptyInput)
+ emptyInput = true;
+ else
+ node = other.node.Clone ();
+ }
+
+ internal XPathNavigator Node {
+ get { return node; }
+ }
+
+ public override bool MoveNext ()
+ {
+ if (emptyInput)
+ return false;
+ if (!base.MoveNext ())
+ return false;
+ current = null;
+ return true;
+ }
+
+ public override XPathItem CurrentCore {
+ get {
+ if (current == null)
+ current = node.Clone ();
+ return current;
+ }
+ }
+
+ public virtual bool ReverseAxis {
+ get { return false; }
+ }
+ }
+
+ // <copy original='System.Xml.XPath/Iterator.cs'>
+
+ internal class SelfIterator : NodeIterator
+ {
+ public SelfIterator (XPathNavigator nav, XQueryContext ctx)
+ : base (nav, ctx)
+ {
+ }
+
+ private SelfIterator (SelfIterator other, bool cloneFlag)
+ : base (other, true)
+ {
+ }
+
+ public override XPathSequence Clone ()
+ {
+ return new SelfIterator (this, true);
+ }
+
+ protected override bool MoveNextCore ()
+ {
+ if (Position == 0)
+ return true;
+ return false;
+ }
+ }
+
+ internal class ParentIterator : NodeIterator
+ {
+ public ParentIterator (XPathNavigator nav, XQueryContext ctx)
+ : base (nav, ctx)
+ {
+ }
+
+ private ParentIterator (ParentIterator other, bool cloneFlag)
+ : base (other, true)
+ {
+ }
+
+ public override XPathSequence Clone ()
+ {
+ return new ParentIterator (this, true);
+ }
+
+ protected override bool MoveNextCore ()
+ {
+ if (Position == 0 && Node.MoveToParent ())
+ return true;
+ return false;
+ }
+
+ public override bool ReverseAxis {
+ get { return true; }
+ }
+ }
+
+ internal class ChildIterator : NodeIterator
+ {
+ public ChildIterator (XPathNavigator nav, XQueryContext ctx)
+ : base (nav, ctx)
+ {
+ }
+
+ private ChildIterator (ChildIterator other, bool cloneFlag)
+ : base (other, true)
+ {
+ }
+
+ public override XPathSequence Clone ()
+ {
+ return new ChildIterator (this, true);
+ }
+
+ protected override bool MoveNextCore ()
+ {
+ if (Position == 0)
+ return Node.MoveToFirstChild ();
+ else
+ return Node.MoveToNext ();
+ }
+ }
+
+ internal class FollowingSiblingIterator : NodeIterator
+ {
+ public FollowingSiblingIterator (XPathNavigator nav, XQueryContext ctx)
+ : base (nav, ctx)
+ {
+ }
+
+ private FollowingSiblingIterator (FollowingSiblingIterator other, bool cloneFlag)
+ : base (other, true)
+ {
+ }
+
+ public override XPathSequence Clone ()
+ {
+ return new FollowingSiblingIterator (this, true);
+ }
+
+ protected override bool MoveNextCore ()
+ {
+ return Node.MoveToNext ();
+ }
+ }
+
+ internal class PrecedingSiblingIterator : NodeIterator
+ {
+ bool finished;
+ bool started;
+ XPathNavigator startPosition;
+
+ public PrecedingSiblingIterator (XPathNavigator nav, XQueryContext ctx)
+ : base (nav, ctx)
+ {
+ startPosition = Node.Clone ();
+ }
+
+ private PrecedingSiblingIterator (PrecedingSiblingIterator other, bool cloneFlag)
+ : base (other, true)
+ {
+ startPosition = other.startPosition;
+ started = other.started;
+ finished = other.finished;
+ }
+
+ public override XPathSequence Clone ()
+ {
+ return new PrecedingSiblingIterator (this, true);
+ }
+
+ protected override bool MoveNextCore ()
+ {
+ if (finished)
+ return false;
+ if (!started) {
+ started = true;
+ Node.MoveToFirst ();
+ } else {
+ Node.MoveToNext ();
+ }
+ if (Node.ComparePosition (startPosition) == XmlNodeOrder.Same) {
+ finished = true;
+ return false;
+ }
+ else
+ return true;
+ }
+
+ public override bool ReverseAxis {
+ get { return true; }
+ }
+ }
+
+ internal class AncestorIterator : NodeIterator
+ {
+ bool finished;
+ ArrayList nodes = new ArrayList ();
+
+ public AncestorIterator (XPathNavigator nav, XQueryContext ctx)
+ : base (nav, ctx)
+ {
+ }
+
+ private AncestorIterator (AncestorIterator other, bool cloneFlag)
+ : base (other, true)
+ {
+ finished = other.finished;
+ nodes = other.nodes;
+ }
+
+ public override XPathSequence Clone ()
+ {
+ return new AncestorIterator (this, true);
+ }
+
+ protected override bool MoveNextCore ()
+ {
+ if (finished)
+ return false;
+ if (nodes != null) {
+ nodes = new ArrayList ();
+ while (Node.MoveToParent () && Node.NodeType != XPathNodeType.Root)
+ nodes.Add (Node.Clone ());
+ nodes.Reverse ();
+ }
+ if (nodes.Count >= Position)
+ return false;
+ Node.MoveTo (nodes [Position] as XPathNavigator);
+ return true;
+ }
+
+ public override bool ReverseAxis {
+ get { return true; }
+ }
+
+ public override int Count {
+ get {
+ if (Position == 0)
+ return base.Count;
+ return nodes.Count;
+ }
+ }
+ }
+
+ internal class AncestorOrSelfIterator : NodeIterator
+ {
+ bool finished;
+ ArrayList nodes = new ArrayList ();
+
+ public AncestorOrSelfIterator (XPathNavigator nav, XQueryContext ctx)
+ : base (nav, ctx)
+ {
+ }
+
+ private AncestorOrSelfIterator (AncestorOrSelfIterator other, bool cloneFlag)
+ : base (other, true)
+ {
+ finished = other.finished;
+ nodes = other.nodes;
+ }
+
+ public override XPathSequence Clone ()
+ {
+ return new AncestorOrSelfIterator (this, true);
+ }
+
+ protected override bool MoveNextCore ()
+ {
+ if (finished)
+ return false;
+ if (nodes != null) {
+ nodes = new ArrayList ();
+ do {
+ nodes.Add (Node.Clone ());
+ } while (Node.MoveToParent () && Node.NodeType != XPathNodeType.Root);
+ nodes.Reverse ();
+ }
+ if (nodes.Count >= Position)
+ return false;
+ Node.MoveTo (nodes [Position] as XPathNavigator);
+ return true;
+ }
+
+ public override bool ReverseAxis {
+ get { return true; }
+ }
+
+ public override int Count {
+ get {
+ if (Position == 0)
+ return base.Count;
+ return nodes.Count;
+ }
+ }
+ }
+
+ internal class DescendantIterator : NodeIterator
+ {
+ private int depth;
+ private bool finished;
+
+ public DescendantIterator (XPathNavigator nav, XQueryContext ctx)
+ : base (nav, ctx)
+ {
+ }
+
+ private DescendantIterator (DescendantIterator other, bool cloneFlag)
+ : base (other, true)
+ {
+ finished = other.finished;
+ depth = other.depth;
+ }
+
+ public override XPathSequence Clone ()
+ {
+ return new DescendantIterator (this, true);
+ }
+
+ protected override bool MoveNextCore ()
+ {
+ if (finished)
+ return false;
+
+ if (Node.MoveToFirstChild ()) {
+ depth ++;
+ return true;
+ }
+ while (depth != 0) {
+ if (Node.MoveToNext ())
+ return true;
+
+ if (!Node.MoveToParent ()) // should NEVER fail!
+ throw new XmlQueryException ("There seems some bugs on the XPathNavigator implementation class.");
+ depth --;
+ }
+ finished = true;
+ return false;
+ }
+ }
+
+ internal class DescendantOrSelfIterator : NodeIterator
+ {
+ protected int depth;
+ private bool finished;
+
+ public DescendantOrSelfIterator (XPathNavigator nav, XQueryContext ctx)
+ : base (nav, ctx)
+ {
+ }
+
+ protected DescendantOrSelfIterator (DescendantOrSelfIterator other, bool cloneFlag)
+ : base (other, true)
+ {
+ depth = other.depth;
+ finished = other.finished;
+ }
+
+ public override XPathSequence Clone ()
+ {
+ return new DescendantOrSelfIterator (this, true);
+ }
+
+ protected override bool MoveNextCore ()
+ {
+ if (finished)
+ return false;
+
+ if (Position == 0)
+ return true; // Self
+
+
+ if (Node.MoveToFirstChild ()) {
+ depth ++;
+ return true;
+ }
+ while (depth != 0) {
+ if (Node.MoveToNext ())
+ return true;
+
+ if (!Node.MoveToParent ()) // should NEVER fail!
+ throw new XmlQueryException ("There seems some bugs on the XPathNavigator implementation class.");
+ depth --;
+ }
+ finished = true;
+ return false;
+ }
+ }
+
+ internal class FollowingIterator : NodeIterator
+ {
+ private bool finished;
+
+ public FollowingIterator (XPathNavigator nav, XQueryContext ctx)
+ : base (nav, ctx)
+ {
+ }
+
+ protected FollowingIterator (FollowingIterator other, bool cloneFlag)
+ : base (other, true)
+ {
+ finished = other.finished;
+ }
+
+ public override XPathSequence Clone ()
+ {
+ return new FollowingIterator (this, true);
+ }
+
+ protected override bool MoveNextCore ()
+ {
+ if (finished)
+ return false;
+ if (Position == 0) {
+ // At first, it should not iterate children.
+ if (Node.MoveToNext ())
+ return true;
+ else {
+ while (Node.MoveToParent ())
+ if (Node.MoveToNext ())
+ return true;
+ }
+ } else {
+ if (Node.MoveToFirstChild ())
+ return true;
+ do {
+ if (Node.MoveToNext ())
+ return true;
+ } while (Node.MoveToParent ());
+ }
+ finished = true;
+ return false;
+ }
+ }
+
+ internal class PrecedingIterator : NodeIterator
+ {
+ bool finished;
+ bool started;
+ XPathNavigator startPosition;
+
+ public PrecedingIterator (XPathNavigator nav, XQueryContext ctx)
+ : base (nav, ctx)
+ {
+ startPosition = Node.Clone ();
+ }
+
+ private PrecedingIterator (PrecedingIterator other, bool cloneFlag)
+ : base (other, true)
+ {
+ startPosition = other.startPosition;
+ started = other.started;
+ finished = other.finished;
+ }
+
+ public override XPathSequence Clone ()
+ {
+ return new PrecedingIterator (this, true);
+ }
+
+ protected override bool MoveNextCore ()
+ {
+ if (finished)
+ return false;
+ if (!started) {
+ started = true;
+ Node.MoveToRoot ();
+ }
+ bool loop = true;
+ while (loop) {
+ while (!Node.MoveToFirstChild ()) {
+ while (!Node.MoveToNext ()) {
+ if (!Node.MoveToParent ()) { // Should not finish, at least before startPosition.
+ finished = true;
+ return false;
+ }
+ }
+ break;
+ }
+ if (Node.IsDescendant (startPosition))
+ continue;
+ loop = false;
+ break;
+ }
+ if (Node.ComparePosition (startPosition) != XmlNodeOrder.Before) {
+ // Note that if _nav contains only 1 node, it won't be Same.
+ finished = true;
+ return false;
+ }
+ else
+ return true;
+ }
+
+ public override bool ReverseAxis {
+ get { return true; }
+ }
+ }
+
+ internal class NamespaceIterator : NodeIterator
+ {
+ public NamespaceIterator (XPathNavigator nav, XQueryContext ctx)
+ : base (nav, ctx)
+ {
+ }
+
+ private NamespaceIterator (NamespaceIterator other, bool cloneFlag)
+ : base (other, true)
+ {
+ }
+
+ public override XPathSequence Clone ()
+ {
+ return new NamespaceIterator (this, true);
+ }
+
+ protected override bool MoveNextCore ()
+ {
+ if (Position == 0) {
+ if (Node.MoveToFirstNamespace ())
+ return true;
+ }
+ else if (Node.MoveToNextNamespace ())
+ return true;
+ return false;
+ }
+
+ public override bool ReverseAxis { get { return true; } }
+ }
+
+ internal class AttributeIterator : NodeIterator
+ {
+ public AttributeIterator (XPathNavigator nav, XQueryContext ctx)
+ : base (nav, ctx)
+ {
+ }
+
+ private AttributeIterator (AttributeIterator other, bool cloneFlag)
+ : base (other, true)
+ {
+ }
+
+ public override XPathSequence Clone ()
+ {
+ return new AttributeIterator (this, true);
+ }
+
+ protected override bool MoveNextCore ()
+ {
+ if (Position == 0) {
+ if (Node.MoveToFirstAttribute ())
+ return true;
+ }
+ else if (Node.MoveToNextAttribute ())
+ return true;
+ return false;
+ }
+ }
+
+ // </copy>
+
+ internal class ExprSequenceIterator : XPathSequence
+ {
+ XPathSequence contextSequence;
+ XPathSequence iter;
+ ExprSequence expr;
+ int currentExprIndex;
+
+ public ExprSequenceIterator (XPathSequence iter, ExprSequence expr)
+ : base (iter.Context)
+ {
+ contextSequence = iter;
+ this.expr = expr;
+ }
+
+ private ExprSequenceIterator (ExprSequenceIterator other)
+ : base (other)
+ {
+ if (other.iter != null)
+ iter = other.iter.Clone ();
+ expr = other.expr;
+ contextSequence = other.contextSequence;
+ currentExprIndex = other.currentExprIndex;
+ }
+
+ public override XPathSequence Clone ()
+ {
+ return new ExprSequenceIterator (this);
+ }
+
+ protected override bool MoveNextCore ()
+ {
+ if (iter != null && iter.MoveNext ())
+ return true;
+ while (currentExprIndex < expr.Count) {
+ iter = expr [currentExprIndex++].Evaluate (contextSequence);
+ if (iter.MoveNext ())
+ return true;
+ }
+ return false;
+ }
+
+ public override XPathItem CurrentCore {
+ get { return iter.Current; }
+ }
+ }
+
+ // FLWOR - Order By
+ internal class FLWORIterator : XPathSequence
+ {
+ XPathSequence contextSequence;
+ FLWORExpr expr;
+ ArrayList forStack = new ArrayList ();
+ IEnumerator en;
+ bool finished;
+
+ public FLWORIterator (XPathSequence iter, FLWORExpr expr)
+ : base (iter.Context)
+ {
+ this.contextSequence = iter;
+ this.expr = expr;
+ }
+
+ private FLWORIterator (FLWORIterator other)
+ : base (other)
+ {
+ contextSequence = other.contextSequence;
+ expr = other.expr;
+ forStack = other.forStack.Clone () as ArrayList;
+ if (en != null)
+ en = ((ICloneable) other.en).Clone () as IEnumerator;
+ finished = other.finished;
+ }
+
+ public override XPathSequence Clone ()
+ {
+ return new FLWORIterator (this);
+ }
+
+ protected override bool MoveNextCore ()
+ {
+ if (en == null)
+ en = GetEnumerator ();
+ return en.MoveNext ();
+ }
+
+ public override IEnumerator GetEnumerator ()
+ {
+ return EvaluateRemainingForLet (0);
+ }
+
+ private IEnumerator EvaluateRemainingForLet (int flcPosition)
+ {
+ // Prepare iteration stack
+ if (flcPosition < expr.ForLetClauses.Count) {
+ IEnumerator items = EvaluateRemainingSingleItem (flcPosition, 0);
+ while (items.MoveNext ())
+ yield return items.Current;
+ } else {
+ bool passedFilter = expr.WhereClause == null;
+ if (!passedFilter)
+ passedFilter = expr.WhereClause.EvaluateAsBoolean (contextSequence);
+ if (passedFilter) {
+ IEnumerator ie = expr.ReturnExpr.Evaluate (contextSequence).GetEnumerator ();
+ while (ie.MoveNext ())
+ yield return (XPathItem) ie.Current;
+ }
+ }
+ }
+
+ private IEnumerator EvaluateRemainingSingleItem (int flcPosition, int singlePosition)
+ {
+ if (singlePosition < expr.ForLetClauses [flcPosition].Count) {
+ ForLetSingleBody sb = expr.ForLetClauses [flcPosition] [singlePosition];
+ ForSingleBody fsb = sb as ForSingleBody;
+ if (fsb != null) {
+ XPathSequence backup = contextSequence;
+ contextSequence = fsb.Expression.Evaluate (Context.CurrentSequence);
+ Context.ContextManager.PushCurrentSequence (contextSequence);
+ while (contextSequence.MoveNext ()) {
+ XPathItem forItem = (XPathItem) contextSequence.Current;
+ Context.PushVariable (fsb.PositionalVar, contextSequence.Position);
+ Context.PushVariable (sb.VarName, forItem);
+ // recurse here (including following bindings)
+ IEnumerator items = EvaluateRemainingSingleItem (flcPosition, singlePosition + 1);
+ while (items.MoveNext ())
+ yield return (XPathItem) items.Current;
+ Context.PopVariable ();
+ Context.PopVariable ();
+ }
+ Context.ContextManager.PopCurrentSequence ();
+ contextSequence = backup;
+ } else {
+ Context.PushVariable (sb.VarName, sb.Expression.Evaluate (contextSequence));
+ // recurse here (including following bindings)
+ IEnumerator items = EvaluateRemainingSingleItem (flcPosition, singlePosition + 1);
+ while (items.MoveNext ())
+ yield return (XPathItem) items.Current;
+ Context.PopVariable ();
+ }
+ } else {
+ // evaluate next binding
+ IEnumerator items = EvaluateRemainingForLet (flcPosition + 1);
+ while (items.MoveNext ())
+ yield return (XPathItem) items.Current;
+ }
+ }
+
+ public override XPathItem CurrentCore {
+ get { return (XPathItem) en.Current; }
+ }
+ }
+
+ internal class GroupIterator : XPathSequence
+ {
+ GroupExpr expr;
+ XPathSequence lseq;
+ XPathSequence rseq;
+ bool started;
+ bool left;
+ bool leftFinished;
+ bool rightFinished;
+
+ public GroupIterator (XPathSequence iter, GroupExpr expr)
+ : base (iter.Context)
+ {
+ this.expr = expr;
+ left = true;
+ lseq = expr.Left.EvaluateOrdered (iter);
+ rseq = expr.Right.EvaluateOrdered (iter);
+ }
+
+ private GroupIterator (GroupIterator other)
+ : base (other)
+ {
+ this.expr = other.expr;
+ this.started = other.started;
+ this.left = other.left;
+ this.leftFinished = other.leftFinished;
+ this.rightFinished = other.rightFinished;
+ this.lseq = other.lseq.Clone ();
+ this.rseq = other.rseq.Clone ();
+ }
+
+ public override XPathSequence Clone ()
+ {
+ return new GroupIterator (this);
+ }
+
+ protected override bool MoveNextCore ()
+ {
+ if (leftFinished && rightFinished)
+ return false;
+ bool proceeded = false;
+ if (started) {
+ if (left) {
+ if (!leftFinished && lseq.MoveNext ())
+ proceeded = true;
+ else
+ leftFinished = true;
+ } else {
+ if (rightFinished && rseq.MoveNext ())
+ proceeded = true;
+ else
+ rightFinished = true;
+ }
+ } else {
+ started = true;
+ if (!lseq.MoveNext ()) {
+ leftFinished = true;
+ if (!rseq.MoveNext ()) {
+ rightFinished = true;
+ return false;
+ }
+ left = false;
+ return true;
+ }
+ proceeded = true;
+ if (!rseq.MoveNext ()) {
+ rightFinished = true;
+ return true;
+ }
+ }
+ if (!proceeded) {
+ if (expr.AggregationType == AggregationType.Intersect)
+ return false;
+ left = !leftFinished;
+ return !leftFinished || !rightFinished;
+ }
+
+ XPathNavigator lnav = lseq.Current as XPathNavigator;
+ XPathNavigator rnav = rseq.Current as XPathNavigator;
+ if (lnav == null || rnav == null)
+ throw new XmlQueryException ("XP0006: Evaluation against union, intersect, except expressions must result in nodes.");
+ XmlNodeOrder order = lnav.ComparePosition (rnav);
+ switch (order) {
+ case XmlNodeOrder.Same:
+ switch (expr.AggregationType) {
+ case AggregationType.Union:
+ left = false;
+ if (!lseq.MoveNext ())
+ leftFinished = true;
+ return true;
+ case AggregationType.Intersect:
+ return true;
+ case AggregationType.Except:
+ default:
+ return MoveNext ();
+ }
+ case XmlNodeOrder.Before:
+ left = true;
+ if (expr.AggregationType == AggregationType.Intersect)
+ return MoveNext ();
+ return true;
+ default: // After, Unknown
+ left = false;
+ if (expr.AggregationType == AggregationType.Intersect)
+ return MoveNext ();
+ return true;
+ }
+ }
+
+ public override XPathItem CurrentCore {
+ get { return left ? lseq.Current : rseq.Current; }
+ }
+ }
+
+ internal class AtomizingIterator : XPathSequence
+ {
+ XPathSequence iter;
+
+ public AtomizingIterator (XPathSequence iter)
+ : base (iter.Context)
+ {
+ this.iter = iter;
+ }
+
+ private AtomizingIterator (AtomizingIterator other)
+ : base (other)
+ {
+ iter = other.iter.Clone ();
+ }
+
+ public override XPathSequence Clone ()
+ {
+ return new AtomizingIterator (this);
+ }
+
+ protected override bool MoveNextCore ()
+ {
+ return iter.MoveNext ();
+ }
+
+ public override XPathItem CurrentCore {
+ get {
+ XPathNavigator nav = iter.Current as XPathNavigator;
+ if (nav == null)
+ return (XPathAtomicValue) iter.Current;
+ if (nav.SchemaInfo != null)
+ return new XPathAtomicValue (
+ nav.TypedValue,
+ nav.SchemaInfo.SchemaType);
+ else
+ return new XPathAtomicValue (nav.Value, null);
+ }
+ }
+ }
+
+ internal class ConvertingIterator : XPathSequence
+ {
+ XPathSequence iter;
+ SequenceType type;
+
+ public ConvertingIterator (XPathSequence iter, SequenceType type)
+ : base (iter.Context)
+ {
+ this.iter = iter;
+ this.type = type;
+ }
+
+ private ConvertingIterator (ConvertingIterator other)
+ : base (other)
+ {
+ iter = other.iter.Clone ();
+ type = other.type;
+ }
+
+ public override XPathSequence Clone ()
+ {
+ return new ConvertingIterator (this);
+ }
+
+ protected override bool MoveNextCore ()
+ {
+ return iter.MoveNext ();
+ }
+
+ public override XPathItem CurrentCore {
+ get { return type.Convert (iter.Current); }
+ }
+ }
+
+ internal class TracingIterator : XPathSequence
+ {
+ XPathSequence iter;
+ string format;
+
+ public TracingIterator (XPathSequence iter, string format)
+ : base (iter.Context)
+ {
+ this.iter = iter;
+ this.format = format;
+ }
+
+ private TracingIterator (TracingIterator other)
+ : base (other)
+ {
+ iter = other.iter.Clone ();
+ format = other.format;
+ }
+
+ public override XPathSequence Clone ()
+ {
+ return new TracingIterator (this);
+ }
+
+ protected override bool MoveNextCore ()
+ {
+ if (!iter.MoveNext ())
+ return false;
+ // FIXME: use OnMessageEvent
+ string output = String.Format (format, iter.Current.TypedValue);
+ Context.StaticContext.OnMessageEvent (iter.Current, new QueryEventArgs (output));
+ return true;
+ }
+
+ public override XPathItem CurrentCore {
+ get { return iter.Current; }
+ }
+ }
+
+ internal class QueryEventArgs
+ {
+ string msg;
+
+ public QueryEventArgs (string msg)
+ {
+ this.msg = msg;
+ }
+
+ public string Message {
+ get { return msg; }
+ }
+ }
+
+ internal class ListIterator : XPathSequence
+ {
+ IList list;
+
+ public ListIterator (XQueryContext ctx, IList list)
+ : base (ctx)
+ {
+ if (list is ICloneable)
+ this.list = list;
+ else
+ throw new InvalidOperationException (String.Format ("XQuery internal error: target list is not cloneable. List is {0}.", list != null ? list.GetType ().ToString () : "null argument"));
+ }
+
+ private ListIterator (ListIterator other)
+ : base (other)
+ {
+ this.list = (IList) ((ICloneable) other.list).Clone ();
+ }
+
+ public override XPathSequence Clone ()
+ {
+ return new ListIterator (this);
+ }
+
+ protected override bool MoveNextCore ()
+ {
+ return (Position < list.Count);
+ }
+
+ public override XPathItem CurrentCore {
+ get { return (XPathItem) list [Position - 1]; }
+ }
+ }
+
+ internal class EnumeratorIterator : XPathSequence
+ {
+ IEnumerator list;
+
+ public EnumeratorIterator (XQueryContext ctx, IEnumerable en)
+ : base (ctx)
+ {
+ list = en.GetEnumerator ();
+ if (list is ICloneable)
+ this.list = list;
+ else
+ throw new InvalidOperationException (String.Format ("XQuery internal error: target list's enumerator is not cloneable. List is {0}.", en != null ? en.GetType ().ToString () : "null argument"));
+ }
+
+ private EnumeratorIterator (EnumeratorIterator other)
+ : base (other)
+ {
+ this.list = (IEnumerator) ((ICloneable) other.list).Clone ();
+ }
+
+ public override XPathSequence Clone ()
+ {
+ return new EnumeratorIterator (this);
+ }
+
+ protected override bool MoveNextCore ()
+ {
+ return list.MoveNext ();
+ }
+
+ public override XPathItem CurrentCore {
+ get { return (XPathItem) list.Current; }
+ }
+ }
+
+ internal abstract class WrapperIterator : XPathSequence
+ {
+ XPathSequence source;
+
+ public WrapperIterator (XPathSequence source)
+ : base (source.Context)
+ {
+ this.source = source;
+ }
+
+ protected WrapperIterator (WrapperIterator other, bool flag)
+ : base (other)
+ {
+ source = other.source.Clone ();
+ }
+
+ public XPathSequence Source {
+ get { return source; }
+ }
+
+ public override XPathItem CurrentCore {
+ get { return source.Current; }
+ }
+ }
+
+ internal class RemovalIterator : WrapperIterator
+ {
+ int position;
+
+ public RemovalIterator (XPathSequence source, int position)
+ : base (source)
+ {
+ this.position = position;
+ }
+
+ protected RemovalIterator (RemovalIterator other)
+ : base (other, true)
+ {
+ position = other.position;
+ }
+
+ public override XPathSequence Clone ()
+ {
+ return new RemovalIterator (this);
+ }
+
+ protected override bool MoveNextCore ()
+ {
+ if (!Source.MoveNext ())
+ return false;
+ else if (Source.Position == position) // skip target
+ return Source.MoveNext ();
+ else
+ return true;
+ }
+ }
+
+ internal class InsertingIterator : WrapperIterator
+ {
+ int position;
+ XPathSequence inserts;
+ bool sourceFinished;
+ bool insertsFinished;
+ XPathSequence currentSequence;
+
+ public InsertingIterator (XPathSequence target, int position, XPathSequence inserts)
+ : base (target)
+ {
+ this.position = position;
+ this.inserts = inserts;
+ currentSequence = target;
+ }
+
+ protected InsertingIterator (InsertingIterator other)
+ : base (other)
+ {
+ position = other.position;
+ inserts = other.inserts.Clone ();
+ sourceFinished = other.sourceFinished;
+ insertsFinished = other.insertsFinished;
+ currentSequence =
+ other.inserts == other.currentSequence ?
+ inserts : Source;
+ }
+
+ public override XPathSequence Clone ()
+ {
+ return new InsertingIterator (this);
+ }
+
+ protected override bool MoveNextCore ()
+ {
+ if (insertsFinished && sourceFinished)
+ return false;
+ if (sourceFinished) { // position >= source.Count
+ currentSequence = inserts;
+ if (inserts.MoveNext ())
+ return true;
+ insertsFinished = true;
+ return false;
+ }
+ else if (insertsFinished) { // after insertion
+ if (Source.MoveNext ())
+ return true;
+ sourceFinished = true;
+ return false;
+ }
+ else if (Position >= position - 1) {
+ currentSequence = inserts;
+ if (inserts.MoveNext ())
+ return true;
+ currentSequence = Source;
+ insertsFinished = true;
+ }
+ if (Source.MoveNext ())
+ return true;
+ sourceFinished = true;
+ return MoveNextCore ();
+ }
+
+ public override XPathItem CurrentCore {
+ get { return currentSequence.Current; }
+ }
+ }
+
+ internal class DistinctValueIterator : XPathSequence
+ {
+ XPathSequence items;
+ CultureInfo collation;
+ Hashtable table = new Hashtable ();
+
+ public DistinctValueIterator (XQueryContext ctx, XPathSequence items, CultureInfo collation)
+ : base (ctx)
+ {
+ this.items = items;
+ this.collation = collation;
+ }
+
+ protected DistinctValueIterator (DistinctValueIterator other)
+ : base (other)
+ {
+ items = other.items.Clone ();
+ collation = other.collation;
+ table = (Hashtable) other.table.Clone ();
+ }
+
+ public override XPathSequence Clone ()
+ {
+ return new DistinctValueIterator (this);
+ }
+
+ protected override bool MoveNextCore ()
+ {
+ if (!items.MoveNext ())
+ return false;
+ // FIXME: use collations
+ // FIXME: check if it really works (esp. Uri et.al)
+ if (table.Contains (items.Current.TypedValue))
+ return MoveNextCore ();
+ return true;
+ }
+
+ public override XPathItem CurrentCore {
+ get { return items.Current; }
+ }
+ }
+}
+
+#endif
diff --git a/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XQueryASTCompiler.cs b/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XQueryASTCompiler.cs
new file mode 100755
index 00000000000..2d18e9e676c
--- /dev/null
+++ b/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XQueryASTCompiler.cs
@@ -0,0 +1,265 @@
+//
+// XQueryASTCompiler.cs - XQuery static context compiler
+//
+// Author:
+// Atsushi Enomoto <atsushi@ximian.com>
+//
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+#if NET_2_0
+
+using System;
+using System.Collections;
+using System.Collections.Specialized;
+using System.IO;
+using System.Security.Policy;
+using System.Xml;
+using System.Xml.Query;
+using System.Xml.Schema;
+using Mono.Xml.XQuery;
+using Mono.Xml.XQuery.Parser;
+using Mono.Xml;
+
+namespace Mono.Xml.XPath2
+{
+ internal class XQueryASTCompiler
+ {
+ // Static method
+
+ public static XQueryStaticContext Compile (XQueryModule module, XQueryCompileOptions options, Evidence evidence, XQueryCommandImpl commandImpl)
+ {
+ if (options == null)
+ options = new XQueryCompileOptions ();
+ return new XQueryASTCompiler (module, options, new XQueryCompileContext (), evidence, commandImpl).Compile ();
+ }
+
+ // Constructor
+
+ private XQueryASTCompiler (XQueryModule module, XQueryCompileOptions options, XQueryCompileContext compileContext, Evidence evidence, XQueryCommandImpl commandImpl)
+ {
+ this.module = module;
+ this.options = options;
+ this.compileContext = compileContext;
+ this.evidence = evidence;
+ this.commandImpl = commandImpl;
+
+ inScopeSchemas = new XmlSchemaSet ();
+ localVariables = new Hashtable ();
+ localFunctions = new XQueryFunctionTable ();
+ }
+
+ XQueryModule module;
+ XQueryCompileOptions options;
+ XQueryCompileContext compileContext;
+
+ IXmlNamespaceResolver nsResolver;
+ string defaultFunctionNamespace;
+
+ // FIXME: Is it OK for an XmlSchema to be in two or more set?
+ XmlSchemaSet inScopeSchemas;
+ ArrayList libModuleContexts = new ArrayList ();
+
+ Hashtable localVariables;
+ XQueryFunctionTable localFunctions;
+
+ bool preserveWhitespace; // Xml space policy
+ bool constructionSpace; // construction mode
+ bool defaultOrdered; // Ordering mode
+ string baseUri;
+ Evidence evidence;
+ XQueryCommandImpl commandImpl;
+
+ // methods.
+
+ private XQueryStaticContext Compile ()
+ {
+ CompileProlog ();
+
+ XQueryMainModule main = module as XQueryMainModule;
+ ExprSequence expr = (main != null) ?
+ CompileExprSequence (main.QueryBody) : null;
+
+ return new XQueryStaticContext (
+ options,
+ compileContext,
+ expr,
+ inScopeSchemas,
+ localVariables,
+ localFunctions,
+ module.NSResolver,
+ module.Prolog.DefaultFunctionNamespace,
+ preserveWhitespace,
+ constructionSpace,
+ defaultOrdered,
+ baseUri,
+ evidence,
+ commandImpl);
+ }
+
+ private void CompileProlog ()
+ {
+ Prolog p = module.Prolog;
+
+ // resolve external modules
+ // FIXME: check if external queries are allowed by default.
+ // FIXME: check recursion
+ XmlUrlResolver res = new XmlUrlResolver ();
+ foreach (ModuleImport modimp in p.ModuleImports) {
+ foreach (string uri in modimp.Locations) {
+ Stream s = res.GetEntity (res.ResolveUri (null, uri), null, typeof (Stream)) as Stream;
+ XQueryLibraryModule ext = XQueryParser.Parse (new StreamReader (s)) as XQueryLibraryModule;
+ if (ext == null)
+ throw new XmlQueryCompileException (String.Format ("External module {0} is resolved as a main module, while it should be a library module."));
+ XQueryStaticContext sctx = new XQueryASTCompiler (ext, options, compileContext, evidence, commandImpl).Compile ();
+ libModuleContexts.Add (sctx);
+ }
+ }
+
+ // resolve and compile in-scope schemas
+ foreach (SchemaImport xsimp in p.SchemaImports) {
+ foreach (string uri in xsimp.Locations) {
+ XmlSchema schema = inScopeSchemas.Add (xsimp.Namespace, uri);
+ compileContext.InEffectSchemas.Add (schema);
+ }
+ }
+ inScopeSchemas.Compile ();
+
+ CheckReferences ();
+
+ ResolveVariableReferences ();
+
+ // compile FunctionDeclaration into XQueryFunction
+ foreach (FunctionDeclaration func in p.Functions.Values) {
+ XQueryFunction cfunc = CompileFunction (func);
+ localFunctions.Add (cfunc);
+ }
+ }
+
+ private void CheckReferences ()
+ {
+ XQueryMainModule main = module as XQueryMainModule;
+ if (main != null)
+ main.QueryBody.CheckReference (this);
+ foreach (FunctionDeclaration func in module.Prolog.Functions.Values) {
+ if (!func.External)
+ func.FunctionBody.CheckReference (this);
+ CheckSchemaType (func.ReturnType);
+ foreach (XQueryFunctionArgument param in func.Parameters)
+ CheckSchemaType (param.Type);
+ }
+ }
+
+ internal void CheckSchemaType (SequenceType type)
+ {
+ if (type == null)
+ return;
+ type.ItemType.CheckReference (this);
+ }
+
+ internal void CheckSchemaTypeName (XmlQualifiedName name)
+ {
+ XmlSchemaType type = InternalPool.GetBuiltInType (name);
+ if (type != null)
+ return;
+ throw new XmlQueryCompileException (String.Format ("Unresolved schema type name: {0}", name));
+ }
+
+ internal void CheckVariableName (XmlQualifiedName name)
+ {
+ // This should not be done, since unresolved QName
+ // may be still valid in context of XmlArgumentList
+ // which is supplied at dynamic evaluation phase.
+ /*
+ if (module.Prolog.Variables [name] != null)
+ return;
+ if (localVariables [name] != null)
+ return;
+ foreach (XQueryStaticContext ctx in libModuleContexts)
+ if (ctx.InScopeVariables [name] != null)
+ return;
+ throw new XmlQueryCompileException (String.Format ("Unresolved variable name: {0}", name));
+ */
+ }
+
+ internal void CheckFunctionName (XmlQualifiedName name)
+ {
+ if (XQueryFunction.FindKnownFunction (name) != null)
+ return;
+ if (module.Prolog.Functions [name] != null)
+ return;
+ foreach (XQueryStaticContext ctx in libModuleContexts)
+ if (ctx.InScopeFunctions [name] != null)
+ return;
+ throw new XmlQueryCompileException (String.Format ("Unresolved function name: {0}", name));
+ }
+
+ private void ResolveVariableReferences ()
+ {
+ // TODO
+ }
+
+ internal XmlSchemaType ResolveSchemaType (XmlQualifiedName name)
+ {
+ XmlSchemaType type = InternalPool.GetBuiltInType (name);
+ if (type != null)
+ return type;
+ type = inScopeSchemas.GlobalTypes [name] as XmlSchemaType;
+ if (type != null)
+ return type;
+ return null;
+ }
+
+ private XQueryFunction CompileFunction (FunctionDeclaration func)
+ {
+ if (func.External)
+ return XQueryFunction.FromQName (func.Name);
+ return new XQueryUserFunction (func.Name, func.Parameters.ToArray (), func.FunctionBody.Expr, func.ReturnType);
+ }
+
+ private ExprSequence CompileExprSequence (ExprSequence expr)
+ {
+ for (int i = 0; i < expr.Count; i++)
+ expr [i] = expr [i].Compile (this);
+ return expr;
+ }
+
+ internal void CheckType (ExprSingle expr, SequenceType type)
+ {
+ if (!expr.StaticType.CanConvertTo (type))
+ throw new XmlQueryCompileException (String.Format ("Cannot convert type from {0} to {1}", expr.StaticType, type));
+ }
+
+ internal XQueryFunction ResolveFunction (XmlQualifiedName name)
+ {
+ XQueryFunction func = XQueryFunction.FindKnownFunction (name);
+ if (func == null)
+ func = localFunctions [name];
+
+ if (func != null)
+ return func;
+ else
+ throw new XmlQueryCompileException ("Could not find specified function.");
+ }
+ }
+}
+#endif
diff --git a/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XQueryArithmeticOperator.cs b/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XQueryArithmeticOperator.cs
new file mode 100755
index 00000000000..665a5212eab
--- /dev/null
+++ b/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XQueryArithmeticOperator.cs
@@ -0,0 +1,368 @@
+//
+// XQueryArithmeticOperator.cs
+//
+// Author:
+// Atsushi Enomoto <atsushi@ximian.com>
+//
+//
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+#if NET_2_0
+using System;
+using System.Collections;
+using System.Reflection;
+using System.Xml;
+using System.Xml.Schema;
+using System.Xml.Query;
+using System.Xml.XPath;
+using System.Xml.Xsl;
+using Mono.Xml;
+
+namespace Mono.Xml.XPath2
+{
+ // FIXME: Handle complete type promotion and subtype substitution.
+ // See XQuery 1.0 Appendix B.*.
+ public class XQueryArithmeticOperator
+ {
+ /// <summary>
+ /// x + y
+ /// </summary>
+ public static XPathAtomicValue Add (XPathAtomicValue lvalue, XPathAtomicValue rvalue)
+ {
+ // numeric, date, time, dateTime, yearMonthDuration, dayTimeDuration
+ switch (lvalue.XmlType.TypeCode) {
+
+ // numerics
+ case XmlTypeCode.Integer:
+ switch (rvalue.XmlType.TypeCode) {
+ case XmlTypeCode.Integer:
+ return new XPathAtomicValue (lvalue.ValueAsInt64 + rvalue.ValueAsInt64, rvalue.XmlType);
+ case XmlTypeCode.Decimal:
+ return new XPathAtomicValue (lvalue.ValueAsDecimal + rvalue.ValueAsDecimal, rvalue.XmlType);
+ case XmlTypeCode.Float:
+ case XmlTypeCode.Double:
+ return new XPathAtomicValue (lvalue.ValueAsDouble + rvalue.ValueAsDouble, rvalue.XmlType);
+ }
+ break;
+
+ case XmlTypeCode.Decimal:
+ switch (rvalue.XmlType.TypeCode) {
+ case XmlTypeCode.Integer:
+ case XmlTypeCode.Decimal:
+ return new XPathAtomicValue (lvalue.ValueAsDecimal + rvalue.ValueAsDecimal, rvalue.XmlType);
+ case XmlTypeCode.Float:
+ case XmlTypeCode.Double:
+ return new XPathAtomicValue (lvalue.ValueAsDouble + rvalue.ValueAsDouble, rvalue.XmlType);
+ }
+ break;
+
+ case XmlTypeCode.Float:
+ case XmlTypeCode.Double:
+ switch (rvalue.XmlType.TypeCode) {
+ case XmlTypeCode.Integer:
+ case XmlTypeCode.Decimal:
+ case XmlTypeCode.Float:
+ case XmlTypeCode.Double:
+ return new XPathAtomicValue (lvalue.ValueAsDouble + rvalue.ValueAsDouble, rvalue.XmlType);
+ }
+ break;
+
+ // datetimes
+ case XmlTypeCode.Time:
+ if (rvalue.XmlType.TypeCode == XmlTypeCode.DayTimeDuration)
+ goto case XmlTypeCode.DateTime;
+ break;
+ case XmlTypeCode.DateTime:
+ case XmlTypeCode.Date:
+ switch (rvalue.XmlType.TypeCode) {
+ case XmlTypeCode.YearMonthDuration:
+ case XmlTypeCode.DayTimeDuration:
+ return new XPathAtomicValue (lvalue.ValueAsDateTime + new TimeSpan (rvalue.ValueAsDateTime.Ticks), lvalue.XmlType);
+ }
+ break;
+ // durations
+ case XmlTypeCode.YearMonthDuration:
+ switch (rvalue.XmlType.TypeCode) {
+ case XmlTypeCode.Date:
+ case XmlTypeCode.DateTime:
+ return new XPathAtomicValue (lvalue.ValueAsDateTime + new TimeSpan (rvalue.ValueAsDateTime.Ticks), rvalue.XmlType);
+ case XmlTypeCode.YearMonthDuration:
+ return new XPathAtomicValue (new DateTime (lvalue.ValueAsDateTime.Ticks + rvalue.ValueAsDateTime.Ticks), InternalPool.XdtYearMonthDuration);
+ }
+ break;
+ case XmlTypeCode.DayTimeDuration:
+ switch (rvalue.XmlType.TypeCode) {
+ case XmlTypeCode.Date:
+ case XmlTypeCode.Time:
+ case XmlTypeCode.DateTime:
+ return new XPathAtomicValue (lvalue.ValueAsDateTime + new TimeSpan (rvalue.ValueAsDateTime.Ticks), rvalue.XmlType);
+ case XmlTypeCode.DayTimeDuration:
+ return new XPathAtomicValue (new DateTime (lvalue.ValueAsDateTime.Ticks + rvalue.ValueAsDateTime.Ticks), InternalPool.XdtDayTimeDuration);
+ }
+ break;
+ }
+
+ throw new XmlQueryException (String.Format ("Not allowed arithmetic operation: {0} + {1}", lvalue.XmlType.QualifiedName, rvalue.XmlType.QualifiedName));
+ }
+
+ /// <summary>
+ /// x - y
+ /// </summary>
+ public static XPathAtomicValue Subtract (XPathAtomicValue lvalue, XPathAtomicValue rvalue)
+ {
+ // numeric, date, time, dateTime, yearMonthDuration, dayTimeDuration
+ switch (lvalue.XmlType.TypeCode) {
+
+ // numerics
+ case XmlTypeCode.Integer:
+ switch (rvalue.XmlType.TypeCode) {
+ case XmlTypeCode.Integer:
+ return new XPathAtomicValue (lvalue.ValueAsInt64 - rvalue.ValueAsInt64, rvalue.XmlType);
+ case XmlTypeCode.Decimal:
+ return new XPathAtomicValue (lvalue.ValueAsDecimal - rvalue.ValueAsDecimal, rvalue.XmlType);
+ case XmlTypeCode.Float:
+ case XmlTypeCode.Double:
+ return new XPathAtomicValue (lvalue.ValueAsDouble - rvalue.ValueAsDouble, rvalue.XmlType);
+ }
+ break;
+
+ case XmlTypeCode.Decimal:
+ switch (rvalue.XmlType.TypeCode) {
+ case XmlTypeCode.Integer:
+ case XmlTypeCode.Decimal:
+ return new XPathAtomicValue (lvalue.ValueAsDecimal - rvalue.ValueAsDecimal, rvalue.XmlType);
+ case XmlTypeCode.Float:
+ case XmlTypeCode.Double:
+ return new XPathAtomicValue (lvalue.ValueAsDouble - rvalue.ValueAsDouble, rvalue.XmlType);
+ }
+ break;
+
+ case XmlTypeCode.Float:
+ case XmlTypeCode.Double:
+ switch (rvalue.XmlType.TypeCode) {
+ case XmlTypeCode.Integer:
+ case XmlTypeCode.Decimal:
+ case XmlTypeCode.Float:
+ case XmlTypeCode.Double:
+ return new XPathAtomicValue (lvalue.ValueAsDouble - rvalue.ValueAsDouble, rvalue.XmlType);
+ }
+ break;
+
+ // datetimes
+ case XmlTypeCode.Time:
+ switch (rvalue.XmlType.TypeCode) {
+ case XmlTypeCode.Time:
+ return new XPathAtomicValue (lvalue.ValueAsDateTime - rvalue.ValueAsDateTime, InternalPool.XdtDayTimeDuration);
+ case XmlTypeCode.DayTimeDuration:
+ return new XPathAtomicValue (lvalue.ValueAsDateTime - new TimeSpan (rvalue.ValueAsDateTime.Ticks), lvalue.XmlType);
+ }
+ break;
+
+ case XmlTypeCode.DateTime:
+ switch (rvalue.XmlType.TypeCode) {
+ case XmlTypeCode.DateTime:
+ // FIXME: check fn:subtract-daytimes-yielding-dayTimeDuration()
+ return new XPathAtomicValue (lvalue.ValueAsDateTime - rvalue.ValueAsDateTime, InternalPool.XdtDayTimeDuration);
+ case XmlTypeCode.YearMonthDuration:
+ case XmlTypeCode.DayTimeDuration:
+ return new XPathAtomicValue (lvalue.ValueAsDateTime - new TimeSpan (rvalue.ValueAsDateTime.Ticks), lvalue.XmlType);
+ }
+ break;
+
+ case XmlTypeCode.Date:
+ switch (rvalue.XmlType.TypeCode) {
+ case XmlTypeCode.Date:
+ // FIXME: check fn:subtract-daytimes-yielding-dayTimeDuration()
+ return new XPathAtomicValue (lvalue.ValueAsDateTime - rvalue.ValueAsDateTime, InternalPool.XdtDayTimeDuration);
+ case XmlTypeCode.YearMonthDuration:
+ case XmlTypeCode.DayTimeDuration:
+ return new XPathAtomicValue (lvalue.ValueAsDateTime - new TimeSpan (rvalue.ValueAsDateTime.Ticks), lvalue.XmlType);
+ }
+ break;
+
+ // durations
+ case XmlTypeCode.YearMonthDuration:
+ if (rvalue.XmlType.TypeCode == XmlTypeCode.YearMonthDuration)
+ return new XPathAtomicValue (new TimeSpan (lvalue.ValueAsDateTime.Ticks - rvalue.ValueAsDateTime.Ticks), InternalPool.XdtYearMonthDuration);
+ break;
+ case XmlTypeCode.DayTimeDuration:
+ if (rvalue.XmlType.TypeCode == XmlTypeCode.DayTimeDuration)
+ return new XPathAtomicValue (new TimeSpan (lvalue.ValueAsDateTime.Ticks - rvalue.ValueAsDateTime.Ticks), InternalPool.XdtDayTimeDuration);
+ break;
+ }
+
+ throw new XmlQueryException (String.Format ("Not allowed arithmetic operation: {0} - {1}", lvalue.XmlType.QualifiedName, rvalue.XmlType.QualifiedName));
+ }
+
+ /// <summary>
+ /// x * y
+ /// </summary>
+ public static XPathAtomicValue Multiply (XPathAtomicValue lvalue, XPathAtomicValue rvalue)
+ {
+ // numeric, date, time, dateTime, yearMonthDuration, dayTimeDuration
+ switch (lvalue.XmlType.TypeCode) {
+
+ // numerics
+ case XmlTypeCode.Integer:
+ switch (rvalue.XmlType.TypeCode) {
+ case XmlTypeCode.Integer:
+ return new XPathAtomicValue (lvalue.ValueAsInt64 * rvalue.ValueAsInt64, rvalue.XmlType);
+ case XmlTypeCode.Decimal:
+ return new XPathAtomicValue (lvalue.ValueAsDecimal * rvalue.ValueAsDecimal, rvalue.XmlType);
+ case XmlTypeCode.Float:
+ case XmlTypeCode.Double:
+ return new XPathAtomicValue (lvalue.ValueAsDouble * rvalue.ValueAsDouble, rvalue.XmlType);
+
+ case XmlTypeCode.DayTimeDuration:
+ case XmlTypeCode.YearMonthDuration:
+ goto case XmlTypeCode.Decimal;
+ }
+ break;
+
+ case XmlTypeCode.Decimal:
+ switch (rvalue.XmlType.TypeCode) {
+ case XmlTypeCode.Integer:
+ case XmlTypeCode.Decimal:
+ return new XPathAtomicValue (lvalue.ValueAsDecimal * rvalue.ValueAsDecimal, rvalue.XmlType);
+ case XmlTypeCode.Float:
+ case XmlTypeCode.Double:
+ return new XPathAtomicValue (lvalue.ValueAsDouble * rvalue.ValueAsDouble, rvalue.XmlType);
+
+ case XmlTypeCode.YearMonthDuration:
+ case XmlTypeCode.DayTimeDuration:
+ return new XPathAtomicValue (new TimeSpan ((long) (lvalue.ValueAsDateTime.Ticks * rvalue.ValueAsDecimal)), rvalue.XmlType);
+ }
+ break;
+
+ case XmlTypeCode.Float:
+ case XmlTypeCode.Double:
+ switch (rvalue.XmlType.TypeCode) {
+ case XmlTypeCode.Integer:
+ case XmlTypeCode.Decimal:
+ case XmlTypeCode.Float:
+ case XmlTypeCode.Double:
+ return new XPathAtomicValue (lvalue.ValueAsDouble * rvalue.ValueAsDouble, rvalue.XmlType);
+
+ case XmlTypeCode.DayTimeDuration:
+ case XmlTypeCode.YearMonthDuration:
+ goto case XmlTypeCode.Decimal;
+ }
+ break;
+
+ // durations
+ case XmlTypeCode.DayTimeDuration:
+ case XmlTypeCode.YearMonthDuration:
+ switch (rvalue.XmlType.TypeCode) {
+ case XmlTypeCode.Integer:
+ case XmlTypeCode.Decimal:
+ case XmlTypeCode.Float:
+ case XmlTypeCode.Double:
+ return Multiply (rvalue, lvalue);
+ }
+ break;
+ }
+
+ throw new XmlQueryException (String.Format ("Not allowed arithmetic operation: {0} * {1}", lvalue.XmlType.QualifiedName, rvalue.XmlType.QualifiedName));
+ }
+
+ /// <summary>
+ /// x / y
+ /// </summary>
+ public static XPathAtomicValue Divide (XPathAtomicValue lvalue, XPathAtomicValue rvalue)
+ {
+ // numeric, date, time, dateTime, yearMonthDuration, dayTimeDuration
+ switch (lvalue.XmlType.TypeCode) {
+
+ // numerics
+ case XmlTypeCode.Integer:
+ switch (rvalue.XmlType.TypeCode) {
+ case XmlTypeCode.Integer:
+ return new XPathAtomicValue (lvalue.ValueAsInt64 / rvalue.ValueAsInt64, rvalue.XmlType);
+ case XmlTypeCode.Decimal:
+ return new XPathAtomicValue (lvalue.ValueAsDecimal / rvalue.ValueAsDecimal, rvalue.XmlType);
+ case XmlTypeCode.Float:
+ case XmlTypeCode.Double:
+ return new XPathAtomicValue (lvalue.ValueAsDouble / rvalue.ValueAsDouble, rvalue.XmlType);
+ }
+ break;
+
+ case XmlTypeCode.Decimal:
+ switch (rvalue.XmlType.TypeCode) {
+ case XmlTypeCode.Integer:
+ case XmlTypeCode.Decimal:
+ return new XPathAtomicValue (lvalue.ValueAsDecimal / rvalue.ValueAsDecimal, rvalue.XmlType);
+ case XmlTypeCode.Float:
+ case XmlTypeCode.Double:
+ return new XPathAtomicValue (lvalue.ValueAsDouble / rvalue.ValueAsDouble, rvalue.XmlType);
+ }
+ break;
+
+ case XmlTypeCode.Float:
+ case XmlTypeCode.Double:
+ switch (rvalue.XmlType.TypeCode) {
+ case XmlTypeCode.Integer:
+ case XmlTypeCode.Decimal:
+ case XmlTypeCode.Float:
+ case XmlTypeCode.Double:
+ return new XPathAtomicValue (lvalue.ValueAsDouble / rvalue.ValueAsDouble, rvalue.XmlType);
+
+ case XmlTypeCode.DayTimeDuration:
+ case XmlTypeCode.YearMonthDuration:
+ goto case XmlTypeCode.Decimal;
+ }
+ break;
+
+ // durations
+ case XmlTypeCode.DayTimeDuration:
+ case XmlTypeCode.YearMonthDuration:
+ switch (rvalue.XmlType.TypeCode) {
+ case XmlTypeCode.Integer:
+ case XmlTypeCode.Decimal:
+ case XmlTypeCode.Float:
+ case XmlTypeCode.Double:
+ return new XPathAtomicValue (new DateTime ((long) (lvalue.ValueAsDateTime.Ticks / rvalue.ValueAsDouble)), rvalue.XmlType);
+ }
+ break;
+ }
+
+ throw new XmlQueryException (String.Format ("Not allowed arithmetic operation: {0} div {1}", lvalue.XmlType.QualifiedName, rvalue.XmlType.QualifiedName));
+ }
+
+ /// <summary>
+ /// x idiv y
+ /// </summary>
+ public static XPathAtomicValue IntDivide (XPathAtomicValue lvalue, XPathAtomicValue rvalue)
+ {
+ return new XPathAtomicValue (lvalue.ValueAsInt64 / rvalue.ValueAsInt64, InternalPool.XsInteger);
+ }
+
+ /// <summary>
+ /// x imod y
+ /// </summary>
+ public static XPathAtomicValue Remainder (XPathAtomicValue lvalue, XPathAtomicValue rvalue)
+ {
+ return new XPathAtomicValue (lvalue.ValueAsInt64 % rvalue.ValueAsInt64, InternalPool.XsInteger);
+ }
+ }
+}
+#endif
diff --git a/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XQueryCliFunction.cs b/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XQueryCliFunction.cs
new file mode 100755
index 00000000000..c081a5b6cdb
--- /dev/null
+++ b/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XQueryCliFunction.cs
@@ -0,0 +1,210 @@
+//
+// XQueryCliFunction.cs
+//
+// Author:
+// Atsushi Enomoto <atsushi@ximian.com>
+//
+//
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+//
+// Runtime type method wrapper for XPath2 function.
+//
+#if NET_2_0
+using System;
+using System.Collections;
+using System.Reflection;
+using System.Security;
+using System.Security.Policy;
+using System.Xml;
+using System.Xml.Schema;
+using System.Xml.Query;
+using System.Xml.XPath;
+using System.Xml.Xsl;
+using Mono.Xml;
+
+namespace Mono.Xml.XPath2
+{
+
+ // Ideas:
+ // declare function namespace cli = "http://mono-project.com/xquery/function/cli"
+ // declare variable v = cli:invoke (cli:new (Microsoft.CSharp:CSharpCodeProvider), CreateCompiler);
+ // declare variable v2 = System.Math:Abs (0.5);
+ //
+
+ public class XQueryCliFunction : XQueryFunction
+ {
+ internal static XQueryCliFunction CreateFromMethodInfo (MethodInfo mi)
+ {
+ return CreateFromMethodInfo (null, mi);
+ }
+
+ internal static XQueryCliFunction CreateFromMethodInfo (XmlQualifiedName name, MethodInfo mi)
+ {
+ return CreateFromMethodInfo (name, new MethodInfo [] {mi});
+ }
+
+ internal static XQueryCliFunction CreateFromMethodInfo (MethodInfo [] methods)
+ {
+ return CreateFromMethodInfo (null, methods);
+ }
+
+ internal static XQueryCliFunction CreateFromMethodInfo (XmlQualifiedName name, MethodInfo [] methodList)
+ {
+ if (methodList == null || methodList.Length == 0)
+ throw new ArgumentException (String.Format ("Argument methods is missing or zero-length array. Name is {0}", name));
+
+ Type cliReturnType = null;
+ ArrayList arguments = new ArrayList ();
+
+ if (name == null || name == XmlQualifiedName.Empty)
+ name = new XmlQualifiedName (methodList [0].Name, methodList [0].DeclaringType.FullName);
+
+ int maxArgs = 0;
+ int minArgs = -1;
+ Hashtable methods = new Hashtable ();
+
+ foreach (MethodInfo mi in methodList) {
+ if (cliReturnType == null)
+ cliReturnType = mi.ReturnType;
+ else if (mi.ReturnType != cliReturnType)
+ throw new ArgumentException (String.Format ("Every XQuery functions which share the same name must have the same return type. Method name is {0}.", mi.Name));
+ ParameterInfo [] prms = mi.GetParameters ();
+
+ int args = prms.Length;
+
+ // Whether it takes "current context" or not.
+ Type t = args > 0 ? prms [0].ParameterType : null;
+ bool ctxSeq = mi.GetCustomAttributes (typeof (XQueryFunctionContextAttribute), false).Length > 0;
+ bool hasContextArg = ctxSeq || t == typeof (XQueryContext);
+ if (ctxSeq || hasContextArg)
+ args--;
+ if (methods [args] != null)
+ throw new ArgumentException (String.Format ("XQuery does not allow functions that accepts such methods that have the same number of parameters in different types. Method name is {0}", mi.Name));
+ methods.Add ((int) args, mi);
+ if (args < minArgs || minArgs < 0)
+ minArgs = args;
+ if (args > maxArgs)
+ maxArgs = args;
+ }
+
+ MethodInfo m = (MethodInfo) methods [(int) maxArgs];
+ if (m == null)
+ throw new SystemException ("Should not happen: maxArgs is " + maxArgs);
+ ParameterInfo [] pl = m.GetParameters ();
+ for (int i = 0; i < pl.Length; i++) {
+ Type t = pl [i].ParameterType;
+ if (t != typeof (XQueryContext))
+ arguments.Add (
+ new XQueryFunctionArgument (new XmlQualifiedName (pl [i].Name), SequenceType.Create (pl [i].ParameterType)));
+ }
+
+ return new XQueryCliFunction (name,
+ arguments.ToArray (typeof (XQueryFunctionArgument)) as XQueryFunctionArgument [],
+ SequenceType.Create (cliReturnType),
+ methods,
+ minArgs,
+ maxArgs);
+ }
+
+ private XQueryCliFunction (XmlQualifiedName name,
+ XQueryFunctionArgument [] args,
+ SequenceType returnType,
+ Hashtable methods,
+ int minArgs,
+ int maxArgs)
+ : base (name, args, returnType)
+ {
+ this.methods = methods;
+ this.maxArgs = maxArgs;
+ this.minArgs = minArgs;
+ }
+
+ // instance members
+
+ // [int argsize] -> MethodInfo (according to the spec 1.1,
+ // there should be no overloads that accepts the same parameter
+ // count in different types).
+ Hashtable methods = new Hashtable ();
+ int maxArgs = 0;
+ int minArgs = -1;
+ SequenceType returnType;
+
+ public override int MinArgs {
+ get { return minArgs; }
+ }
+
+ public override int MaxArgs {
+ get { return maxArgs; }
+ }
+
+ public override object Invoke (XPathSequence current, object [] args)
+ {
+ MethodInfo mi = methods [args.Length] as MethodInfo;
+ if (mi == null)
+ throw new ArgumentException ("The number of custom function parameter does not match with the registered method's signature.");
+ ParameterInfo [] prms = mi.GetParameters ();
+
+ // Use Evidence and PermissionSet.Demand() here
+ // before invoking external function.
+ Evidence e = current.Context.StaticContext.Evidence;
+ if (e != null)
+ SecurityManager.ResolvePolicy (e).Demand ();
+
+ Type t = prms.Length > 0 ? prms [0].ParameterType : null;
+ bool ctxSeq = mi.GetCustomAttributes (
+ typeof (XQueryFunctionContextAttribute),
+ false).Length > 0;
+ if (t == typeof (XQueryContext)) {
+ ArrayList pl = new ArrayList (args);
+ pl.Insert (0, current.Context);
+ args = pl.ToArray ();
+ }
+ else if (ctxSeq) {
+ ArrayList pl = new ArrayList (args);
+ pl.Insert (0, current);
+ args = pl.ToArray ();
+ }
+
+ if (args.Length != prms.Length)
+ throw new XmlQueryException (String.Format ("Argument numbers were different for function {0}. Signature requires {1} while actual call was {2}.", mi.Name, prms.Length, args.Length));
+
+ // If native parameter type is XPathSequence and the actual values are not, adjust them
+ for (int i = 0; i < args.Length; i++) {
+ if (prms [i].ParameterType == typeof (XPathSequence) && !(args [i] is XPathSequence)) {
+ XPathItem item = args [i] as XPathItem;
+ if (item == null)
+ item = args [i] == null ? null : new XPathAtomicValue (args [i], InternalPool.GetBuiltInType (InternalPool.XmlTypeCodeFromRuntimeType (prms [i].ParameterType, true)));
+ if (item == null)
+ args [i] = new XPathEmptySequence (current.Context);
+ else
+ args [i] = new SingleItemIterator (item, current.Context);
+ }
+ }
+
+ return mi.Invoke (null, args);
+ }
+ }
+
+}
+#endif
diff --git a/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XQueryCommandImpl.cs b/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XQueryCommandImpl.cs
new file mode 100755
index 00000000000..e77ec257e23
--- /dev/null
+++ b/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XQueryCommandImpl.cs
@@ -0,0 +1,100 @@
+//
+// XQueryCommandImpl.cs - core XQueryCommand implementation in System.Xml.dll
+//
+// Author:
+// Atsushi Enomoto <atsushi@ximian.com>
+//
+//
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+#if NET_2_0
+using System;
+using System.Collections;
+using System.IO;
+using System.Reflection;
+using System.Security.Policy;
+using System.Xml;
+using System.Xml.Query;
+using System.Xml.XPath;
+using Mono.Xml.XPath2;
+using Mono.Xml.XQuery.Parser;
+
+namespace Mono.Xml.XPath2
+{
+ public class XQueryCommandImpl
+ {
+ MethodInfo xqueryCommandOnMessageEventMethod;
+
+ MethodInfo GetEventHandler (object qobj)
+ {
+ if (xqueryCommandOnMessageEventMethod == null) {
+ EventInfo ei = qobj.GetType ().GetEvent ("OnMessageEvent");
+ xqueryCommandOnMessageEventMethod = ei.GetRaiseMethod (true);
+ }
+ return xqueryCommandOnMessageEventMethod;
+ }
+
+ XQueryStaticContext staticContext;
+ object xqueryCommand;
+
+ public XQueryCommandImpl ()
+ {
+ }
+
+ public void Compile (TextReader input, Evidence evidence, object xqueryCommand)
+ {
+ staticContext = XQueryASTCompiler.Compile (XQueryParser.Parse (input), null, evidence, this);
+ this.xqueryCommand = xqueryCommand;
+ // FIXME: generate executable assembly, and load it with evidence.
+ }
+
+ public void Execute (XPathNavigator input, XmlResolver resolver, XmlArgumentList args, XmlWriter writer)
+ {
+ if (staticContext == null)
+ throw new XmlQueryException ("Query string is not compiled.");
+ // Initialize event handler method info.
+ xqueryCommandOnMessageEventMethod = null;
+
+ XQueryContext ctx = new XQueryContext (new XQueryContextManager (staticContext, input, writer, resolver, args));
+
+ XPathSequence iter = new SingleItemIterator (input, ctx);
+
+ foreach (ExprSingle expr in staticContext.QueryBody)
+ expr.Serialize (iter);
+ }
+
+ internal void ProcessMessageEvent (object sender, QueryEventArgs e)
+ {
+ // FIXME: how to handle event raise method?
+ throw new NotImplementedException ();
+ /*
+ MethodInfo mi = GetEventHandler (xqueryCommand);
+ if (mi != null)
+ mi.Invoke (xqueryCommand, new object [] {sender, e});
+ */
+ }
+ }
+
+}
+
+#endif
diff --git a/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XQueryComparisonOperator.cs b/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XQueryComparisonOperator.cs
new file mode 100755
index 00000000000..c7f7301afb5
--- /dev/null
+++ b/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XQueryComparisonOperator.cs
@@ -0,0 +1,235 @@
+//
+// XQueryComparisonOperator.cs
+//
+// Author:
+// Atsushi Enomoto <atsushi@ximian.com>
+//
+//
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+#if NET_2_0
+using System;
+using System.Collections;
+using System.Reflection;
+using System.Xml;
+using System.Xml.Schema;
+using System.Xml.Query;
+using System.Xml.XPath;
+using System.Xml.Xsl;
+
+namespace Mono.Xml.XPath2
+{
+ // FIXME: Handle complete type promotion and subtype substitution.
+ // See XQuery 1.0 Appendix B.*.
+ public class XQueryComparisonOperator
+ {
+ private static bool OpBooleanLessThan (bool b1, bool b2)
+ {
+ return !b1 && b2;
+ }
+
+ private static bool OpBooleanGreaterThan (bool b1, bool b2)
+ {
+ return b1 && !b2;
+ }
+
+ private static bool CompareEquality (XPathAtomicValue lvalue, XPathAtomicValue rvalue)
+ {
+ switch (lvalue.XmlType.TypeCode) {
+ case XmlTypeCode.Boolean:
+ return lvalue.ValueAsBoolean == rvalue.ValueAsBoolean;
+ case XmlTypeCode.UntypedAtomic:
+ case XmlTypeCode.String:
+ return lvalue.Value == rvalue.Value;
+ case XmlTypeCode.Date:
+ case XmlTypeCode.Time:
+ case XmlTypeCode.DateTime:
+ case XmlTypeCode.YearMonthDuration:
+ case XmlTypeCode.DayTimeDuration:
+ return lvalue.ValueAsDateTime == rvalue.ValueAsDateTime;
+ case XmlTypeCode.HexBinary:
+ case XmlTypeCode.Base64Binary:
+ case XmlTypeCode.AnyUri:
+ case XmlTypeCode.QName:
+ case XmlTypeCode.Notation:
+ throw new NotImplementedException ();
+ }
+ XmlQualifiedName nameL = lvalue.XmlType.QualifiedName != XmlQualifiedName.Empty ? lvalue.XmlType.QualifiedName : new XmlQualifiedName ("anyType", XmlSchema.Namespace);
+ XmlQualifiedName nameR = rvalue.XmlType.QualifiedName != XmlQualifiedName.Empty ? rvalue.XmlType.QualifiedName : new XmlQualifiedName ("anyType", XmlSchema.Namespace);
+ throw new XmlQueryException (String.Format ("Not allowed value comparison between {0} and {1}.", nameL, nameR));
+ }
+
+ public static bool ValueEQ (XPathAtomicValue lvalue, XPathAtomicValue rvalue)
+ {
+ if (lvalue.XmlType.TypeCode == XmlTypeCode.Decimal &&
+ rvalue.XmlType.TypeCode == XmlTypeCode.Decimal)
+ return lvalue.ValueAsDecimal == rvalue.ValueAsDecimal;
+ if (SequenceType.IsNumeric (lvalue.XmlType.TypeCode) &&
+ SequenceType.IsNumeric (lvalue.XmlType.TypeCode))
+ return lvalue.ValueAsDouble == rvalue.ValueAsDouble;
+ if (lvalue.XmlType.TypeCode == rvalue.XmlType.TypeCode)
+ return CompareEquality (lvalue, rvalue);
+
+ throw new XmlQueryException (String.Format ("Not allowed value comparison between {0} and {1}.", lvalue.XmlType.QualifiedName, rvalue.XmlType.QualifiedName));
+ }
+
+ public static bool ValueNE (XPathAtomicValue lvalue, XPathAtomicValue rvalue)
+ {
+ if (lvalue.XmlType.TypeCode == XmlTypeCode.Decimal &&
+ rvalue.XmlType.TypeCode == XmlTypeCode.Decimal)
+ return lvalue.ValueAsDecimal != rvalue.ValueAsDecimal;
+ if (SequenceType.IsNumeric (lvalue.XmlType.TypeCode) &&
+ SequenceType.IsNumeric (lvalue.XmlType.TypeCode))
+ return lvalue.ValueAsDouble != rvalue.ValueAsDouble;
+ if (lvalue.XmlType.TypeCode == rvalue.XmlType.TypeCode)
+ return !CompareEquality (lvalue, rvalue);
+
+ throw new XmlQueryException (String.Format ("Not allowed value comparison between {0} and {1}.", lvalue.XmlType.QualifiedName, rvalue.XmlType.QualifiedName));
+ }
+
+ private static bool CompareLT (XPathAtomicValue lvalue, XPathAtomicValue rvalue)
+ {
+ switch (lvalue.XmlType.TypeCode) {
+ case XmlTypeCode.Boolean:
+ return OpBooleanLessThan (lvalue.ValueAsBoolean, rvalue.ValueAsBoolean);
+ case XmlTypeCode.String:
+ return lvalue.Value == rvalue.Value;
+ case XmlTypeCode.Date:
+ case XmlTypeCode.Time:
+ case XmlTypeCode.DateTime:
+ case XmlTypeCode.YearMonthDuration:
+ case XmlTypeCode.DayTimeDuration:
+ return lvalue.ValueAsDateTime < rvalue.ValueAsDateTime;
+ }
+ throw new XmlQueryException (String.Format ("Not allowed value comparison between {0} and {1}.", lvalue.XmlType.QualifiedName, rvalue.XmlType.QualifiedName));
+ }
+
+ public static bool ValueLT (XPathAtomicValue lvalue, XPathAtomicValue rvalue)
+ {
+ if (lvalue.XmlType.TypeCode == XmlTypeCode.Decimal &&
+ rvalue.XmlType.TypeCode == XmlTypeCode.Decimal)
+ return lvalue.ValueAsDecimal < rvalue.ValueAsDecimal;
+ if (SequenceType.IsNumeric (lvalue.XmlType.TypeCode) &&
+ SequenceType.IsNumeric (lvalue.XmlType.TypeCode))
+ return lvalue.ValueAsDouble < rvalue.ValueAsDouble;
+ if (lvalue.XmlType.TypeCode == rvalue.XmlType.TypeCode)
+ return CompareLT (lvalue, rvalue);
+
+ throw new XmlQueryException (String.Format ("Not allowed value comparison between {0} and {1}.", lvalue.XmlType.QualifiedName, rvalue.XmlType.QualifiedName));
+ }
+
+ private static bool CompareLE (XPathAtomicValue lvalue, XPathAtomicValue rvalue)
+ {
+ switch (lvalue.XmlType.TypeCode) {
+ case XmlTypeCode.Boolean:
+ return !OpBooleanGreaterThan (lvalue.ValueAsBoolean, rvalue.ValueAsBoolean);
+ case XmlTypeCode.String:
+ return lvalue.Value == rvalue.Value;
+ case XmlTypeCode.Date:
+ case XmlTypeCode.Time:
+ case XmlTypeCode.DateTime:
+ case XmlTypeCode.YearMonthDuration:
+ case XmlTypeCode.DayTimeDuration:
+ return lvalue.ValueAsDateTime <= rvalue.ValueAsDateTime;
+ }
+ throw new XmlQueryException (String.Format ("Not allowed value comparison between {0} and {1}.", lvalue.XmlType.QualifiedName, rvalue.XmlType.QualifiedName));
+ }
+
+ public static bool ValueLE (XPathAtomicValue lvalue, XPathAtomicValue rvalue)
+ {
+ if (lvalue.XmlType.TypeCode == XmlTypeCode.Decimal &&
+ rvalue.XmlType.TypeCode == XmlTypeCode.Decimal)
+ return lvalue.ValueAsDecimal <= rvalue.ValueAsDecimal;
+ if (SequenceType.IsNumeric (lvalue.XmlType.TypeCode) &&
+ SequenceType.IsNumeric (lvalue.XmlType.TypeCode))
+ return lvalue.ValueAsDouble <= rvalue.ValueAsDouble;
+ if (lvalue.XmlType.TypeCode == rvalue.XmlType.TypeCode)
+ return CompareLE (lvalue, rvalue);
+
+ throw new XmlQueryException (String.Format ("Not allowed value comparison between {0} and {1}.", lvalue.XmlType.QualifiedName, rvalue.XmlType.QualifiedName));
+ }
+
+ private static bool CompareGT (XPathAtomicValue lvalue, XPathAtomicValue rvalue)
+ {
+ switch (lvalue.XmlType.TypeCode) {
+ case XmlTypeCode.Boolean:
+ return OpBooleanGreaterThan (lvalue.ValueAsBoolean, rvalue.ValueAsBoolean);
+ case XmlTypeCode.String:
+ return lvalue.Value == rvalue.Value;
+ case XmlTypeCode.Date:
+ case XmlTypeCode.Time:
+ case XmlTypeCode.DateTime:
+ case XmlTypeCode.YearMonthDuration:
+ case XmlTypeCode.DayTimeDuration:
+ return lvalue.ValueAsDateTime > rvalue.ValueAsDateTime;
+ }
+ throw new XmlQueryException (String.Format ("Not allowed value comparison between {0} and {1}.", lvalue.XmlType.QualifiedName, rvalue.XmlType.QualifiedName));
+ }
+
+ public static bool ValueGT (XPathAtomicValue lvalue, XPathAtomicValue rvalue)
+ {
+ if (lvalue.XmlType.TypeCode == XmlTypeCode.Decimal &&
+ rvalue.XmlType.TypeCode == XmlTypeCode.Decimal)
+ return lvalue.ValueAsDecimal > rvalue.ValueAsDecimal;
+ if (SequenceType.IsNumeric (lvalue.XmlType.TypeCode) &&
+ SequenceType.IsNumeric (lvalue.XmlType.TypeCode))
+ return lvalue.ValueAsDouble > rvalue.ValueAsDouble;
+ if (lvalue.XmlType.TypeCode == rvalue.XmlType.TypeCode)
+ return CompareGT (lvalue, rvalue);
+
+ throw new XmlQueryException (String.Format ("Not allowed value comparison between {0} and {1}.", lvalue.XmlType.QualifiedName, rvalue.XmlType.QualifiedName));
+ }
+
+ private static bool CompareGE (XPathAtomicValue lvalue, XPathAtomicValue rvalue)
+ {
+ switch (lvalue.XmlType.TypeCode) {
+ case XmlTypeCode.Boolean:
+ return !OpBooleanLessThan (lvalue.ValueAsBoolean, rvalue.ValueAsBoolean);
+ case XmlTypeCode.String:
+ return lvalue.Value == rvalue.Value;
+ case XmlTypeCode.Date:
+ case XmlTypeCode.Time:
+ case XmlTypeCode.DateTime:
+ case XmlTypeCode.YearMonthDuration:
+ case XmlTypeCode.DayTimeDuration:
+ return lvalue.ValueAsDateTime >= rvalue.ValueAsDateTime;
+ }
+ throw new XmlQueryException (String.Format ("Not allowed value comparison between {0} and {1}.", lvalue.XmlType.QualifiedName, rvalue.XmlType.QualifiedName));
+ }
+
+ public static bool ValueGE (XPathAtomicValue lvalue, XPathAtomicValue rvalue)
+ {
+ if (lvalue.XmlType.TypeCode == XmlTypeCode.Decimal &&
+ rvalue.XmlType.TypeCode == XmlTypeCode.Decimal)
+ return lvalue.ValueAsDecimal >= rvalue.ValueAsDecimal;
+ if (SequenceType.IsNumeric (lvalue.XmlType.TypeCode) &&
+ SequenceType.IsNumeric (lvalue.XmlType.TypeCode))
+ return lvalue.ValueAsDouble >= rvalue.ValueAsDouble;
+ if (lvalue.XmlType.TypeCode == rvalue.XmlType.TypeCode)
+ return CompareGE (lvalue, rvalue);
+
+ throw new XmlQueryException (String.Format ("Not allowed value comparison between {0} and {1}.", lvalue.XmlType.QualifiedName, rvalue.XmlType.QualifiedName));
+ }
+ }
+}
+#endif
diff --git a/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XQueryCompileContext.cs b/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XQueryCompileContext.cs
new file mode 100755
index 00000000000..c49d8f194b5
--- /dev/null
+++ b/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XQueryCompileContext.cs
@@ -0,0 +1,93 @@
+//
+// XQueryCompileContext.cs
+//
+// Author:
+// Atsushi Enomoto <atsushi@ximian.com>
+//
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+#if NET_2_0
+
+using System;
+using System.Collections;
+using System.Collections.Specialized;
+using System.Xml;
+using System.Xml.Query;
+using System.Xml.Schema;
+using Mono.Xml.XPath2;
+
+namespace Mono.Xml.XPath2
+{
+ // Holds dynamic compile context that is shared between one or more
+ // compilers that are created during one XQueryCommand.Compile().
+ internal class XQueryCompileContext
+ {
+ public XQueryCompileContext ()
+ {
+ schemaCache = new Hashtable ();
+ moduleCache = new Hashtable ();
+
+ inEffectSchemas = new XmlSchemaSet ();
+ inEffectVariables = new Hashtable ();
+ inEffectFunctions = new XQueryFunctionTable ();
+ }
+
+ // Compiled schema table; It is used to avoid multiple time
+ // compilation of the same schemas that is likely to happen
+ // when a library module is divided into multiple files.
+ // [location string] -> XmlSchema (done) or null (not).
+ IDictionary schemaCache;
+ // ditto for local module resources.
+ // [location] -> XQueryLibraryModule (done) or null (not).
+ IDictionary moduleCache;
+
+ // Collects the whole schemas, variables and functions.
+ XmlSchemaSet inEffectSchemas;
+ Hashtable inEffectVariables;
+ XQueryFunctionTable inEffectFunctions;
+
+ public IDictionary SchemaCache {
+ get { return schemaCache; }
+ }
+
+ public IDictionary ModuleCache {
+ get { return moduleCache; }
+ }
+
+ // Compilation results
+
+ public XmlSchemaSet InEffectSchemas {
+ get { return inEffectSchemas; }
+ }
+
+ public Hashtable InEffectVariables {
+ get { return inEffectVariables; }
+ }
+
+ public XQueryFunctionTable InEffectFunctions {
+ get { return inEffectFunctions; }
+ }
+ }
+}
+
+#endif
diff --git a/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XQueryCompileOptions.cs b/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XQueryCompileOptions.cs
new file mode 100755
index 00000000000..b4e0f8192aa
--- /dev/null
+++ b/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XQueryCompileOptions.cs
@@ -0,0 +1,101 @@
+//
+// XQueryCompileOptions.cs - XQuery compiler option stucture.
+//
+// Author:
+// Atsushi Enomoto <atsushi@ximian.com>
+//
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+#if NET_2_0
+
+using System;
+using System.Collections;
+using System.Collections.Specialized;
+using System.Globalization;
+using System.Xml;
+using System.Xml.Query;
+using System.Xml.Schema;
+using Mono.Xml.XPath2;
+
+namespace Mono.Xml.XPath2
+{
+ public class XQueryCompileOptions
+ {
+ public XQueryCompileOptions ()
+ : this (new NameTable (), null)
+ {
+ }
+
+ public XQueryCompileOptions (XmlNameTable nameTable, CultureInfo defaultCollation)
+ {
+ this.nameTable = nameTable;
+ this.defaultCollation = defaultCollation;
+ if (this.defaultCollation == null)
+ this.defaultCollation = CultureInfo.InvariantCulture;
+
+ knownCollections = new Hashtable ();
+ }
+
+ XmlNameTable nameTable;
+ XmlQueryDialect compat;
+ CultureInfo defaultCollation;
+ Hashtable knownCollections;
+ bool xqueryFlagger;
+ bool xqueryStaticFlagger;
+
+ // XPath 1.0 Compatibility Mode.
+ public XmlQueryDialect Compatibility {
+ get { return compat; }
+ set { compat = value; }
+ }
+
+ public XmlNameTable NameTable {
+ get { return nameTable; }
+ set { nameTable = value; }
+ }
+
+ public CultureInfo DefaultCollation {
+ get { return defaultCollation; }
+ set { defaultCollation = value; }
+ }
+
+ // FIXME: implement
+ public bool XQueryFlagger {
+ get { return xqueryFlagger; }
+ set { xqueryFlagger = value; }
+ }
+
+ // FIXME: implement
+ public bool XQueryStaticFlagger {
+ get { return xqueryStaticFlagger; }
+ set { xqueryStaticFlagger = value; }
+ }
+
+ // FIXME: implement
+ public Hashtable KnownCollections {
+ get { return knownCollections; }
+ }
+ }
+}
+
+#endif
diff --git a/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XQueryContext.cs b/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XQueryContext.cs
new file mode 100755
index 00000000000..c4367efcb80
--- /dev/null
+++ b/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XQueryContext.cs
@@ -0,0 +1,318 @@
+//
+// XQueryContext.cs - XQuery/XPath2 dynamic context
+//
+// Author:
+// Atsushi Enomoto <atsushi@ximian.com>
+//
+//
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+#if NET_2_0
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Xml;
+using System.Xml.Schema;
+using System.Xml.XPath;
+using System.Xml.Query;
+using Mono.Xml;
+
+namespace Mono.Xml.XPath2
+{
+ internal class XQueryContextManager
+ {
+ XQueryStaticContext staticContext;
+
+ // Fixed dynamic context during evaluation
+ XmlArgumentList args;
+ XmlResolver extDocResolver;
+
+ Stack<XQueryContext> contextStack = new Stack<XQueryContext> ();
+ XQueryContext currentContext;
+#if SEEMS_CONTEXT_FOR_CURRENT_REQURED
+#else
+ Stack<XPathSequence> contextSequenceStack = new Stack<XPathSequence> ();
+#endif
+ XmlWriter currentWriter;
+ XPathItem input; // source input item(node)
+ XPathSequence currentSequence;
+ XmlNamespaceManager namespaceManager;
+ Hashtable localCollationCache = new Hashtable ();
+
+ internal XQueryContextManager (XQueryStaticContext ctx, XPathItem input, XmlWriter writer, XmlResolver resolver, XmlArgumentList args)
+ {
+ this.input = input;
+ this.staticContext = ctx;
+ this.args = args;
+ currentWriter = writer;
+ this.extDocResolver = resolver;
+
+ namespaceManager = new XmlNamespaceManager (ctx.NameTable);
+ foreach (DictionaryEntry de in ctx.NSResolver.GetNamespacesInScope (XmlNamespaceScope.ExcludeXml))
+ namespaceManager.AddNamespace (de.Key.ToString (), de.Value.ToString ());
+ namespaceManager.PushScope ();
+
+ currentContext = new XQueryContext (this, null, new Hashtable ());
+ if (input != null) {
+ currentSequence = new SingleItemIterator (input, currentContext);
+ currentSequence.MoveNext ();
+ }
+ currentContext = new XQueryContext (this, currentSequence, new Hashtable ());
+ }
+
+ public bool Initialized {
+ get { return currentContext != null; }
+ }
+
+ public XmlResolver ExtDocResolver {
+ get { return extDocResolver; }
+ }
+
+ public XmlArgumentList Arguments {
+ get { return args; }
+ }
+
+ public XmlWriter Writer {
+ get { return currentWriter; }
+ // FIXME: might be better avoid setter as public
+ set { currentWriter = value; }
+ }
+
+ internal XQueryContext CurrentContext {
+ get { return currentContext; }
+ }
+
+ internal XQueryStaticContext StaticContext {
+ get { return staticContext; }
+ }
+
+ internal CultureInfo GetCulture (string collation)
+ {
+ CultureInfo ci = staticContext.GetCulture (collation);
+ if (ci == null)
+ ci = (CultureInfo) localCollationCache [collation];
+ if (ci != null)
+ return ci;
+ ci = new CultureInfo (collation);
+ localCollationCache [collation] = ci;
+ return ci;
+ }
+
+ public void PushCurrentSequence (XPathSequence sequence)
+ {
+ if (sequence == null)
+ throw new ArgumentNullException ();
+// sequence = sequence.Clone ();
+#if SEEMS_CONTEXT_FOR_CURRENT_REQURED
+ contextStack.Push (currentContext);
+ currentsequence = sequence;
+ currentContext = new XQueryContext (this);
+#else
+ contextSequenceStack.Push (currentSequence);
+ currentSequence = sequence;
+#endif
+ }
+
+ public void PopCurrentSequence ()
+ {
+#if SEEMS_CONTEXT_FOR_CURRENT_REQURED
+ PopContext ();
+#else
+ currentSequence = contextSequenceStack.Pop ();
+#endif
+ if (currentSequence == null)
+ throw new SystemException ("XQuery error: should not happen.");
+ }
+
+ internal void PushContext ()
+ {
+ contextStack.Push (currentContext);
+ currentContext = new XQueryContext (this);
+ }
+
+ internal void PopContext ()
+ {
+ currentContext = contextStack.Pop ();
+ }
+
+ internal void PushVariable (XmlQualifiedName name, object iter)
+ {
+ PushContext ();
+ CurrentContext.SetVariable (name, iter);
+ }
+
+ internal void PopVariable ()
+ {
+ PopContext ();
+ }
+
+ internal XmlNamespaceManager NSManager {
+ get { return namespaceManager; }
+ }
+
+ internal XPathSequence CurrentSequence {
+ get { return currentSequence; }
+ }
+ }
+
+ public class XQueryContext : IXmlNamespaceResolver
+ {
+ XQueryContextManager contextManager;
+ Hashtable currentVariables;
+ XPathSequence currentSequence;
+
+ internal XQueryContext (XQueryContextManager manager)
+ : this (manager,
+ manager.CurrentSequence,
+ (Hashtable) manager.CurrentContext.currentVariables.Clone ())
+ {
+ }
+
+ internal XQueryContext (XQueryContextManager manager, XPathSequence currentSequence, Hashtable currentVariables)
+ {
+ contextManager = manager;
+ this.currentSequence = currentSequence;
+/*
+ if (manager.CurrentContext != null)
+ currentVariables = (Hashtable) manager.CurrentContext.currentVariables.Clone ();
+ else
+ currentVariables = new Hashtable ();
+*/
+ this.currentVariables = currentVariables;
+ }
+
+ internal XmlWriter Writer {
+ get { return contextManager.Writer; }
+ // FIXME: might be better avoid public setter.
+ set { contextManager.Writer = value; }
+ }
+
+ internal XQueryStaticContext StaticContext {
+ get { return contextManager.StaticContext; }
+ }
+
+ internal CultureInfo DefaultCollation {
+ get { return StaticContext.DefaultCollation; }
+ }
+
+ internal XQueryContextManager ContextManager {
+ get { return contextManager; }
+ }
+
+ public XPathItem CurrentItem {
+ get {
+ if (currentSequence == null)
+ throw new XmlQueryException ("This XQuery dynamic context has no context item.");
+ return CurrentSequence.Current;
+ }
+ }
+
+ public XPathNavigator CurrentNode {
+ get { return CurrentItem as XPathNavigator; }
+ }
+
+ public XPathSequence CurrentSequence {
+ get { return currentSequence; }
+ }
+
+ internal CultureInfo GetCulture (string collation)
+ {
+ return contextManager.GetCulture (collation);
+ }
+
+ internal void PushVariable (XmlQualifiedName name, object iter)
+ {
+ contextManager.PushVariable (name, iter);
+ }
+
+ // FIXME: Hmm... this design is annoying.
+ internal void SetVariable (XmlQualifiedName name, object iter)
+ {
+ currentVariables [name] = iter;
+ }
+
+ internal void PopVariable ()
+ {
+ contextManager.PopVariable ();
+ }
+
+ internal XPathSequence ResolveVariable (XmlQualifiedName name)
+ {
+ object obj = currentVariables [name];
+ if (obj == null && contextManager.Arguments != null)
+ obj = contextManager.Arguments.GetParameter (name.Name, name.Namespace);
+ if (obj == null)
+ return new XPathEmptySequence (this);
+ XPathSequence seq = obj as XPathSequence;
+ if (seq != null)
+ return seq;
+ XPathItem item = obj as XPathItem;
+ if (item == null)
+ item = new XPathAtomicValue (obj, InternalPool.GetBuiltInType (InternalPool.XmlTypeCodeFromRuntimeType (obj.GetType (), true)));
+ return new SingleItemIterator (item, this);
+ }
+
+ internal XPathSequence ResolveCollection (string name)
+ {
+ // FIXME: support later.
+ return new XPathEmptySequence (currentSequence.Context);
+ }
+
+ public IXmlNamespaceResolver NSResolver {
+ get { return contextManager.NSManager; }
+ }
+
+ #region IXmlNamespaceResolver implementation
+ public XmlNameTable NameTable {
+ get { return contextManager.NSManager.NameTable; }
+ }
+
+ public string LookupPrefix (string ns)
+ {
+ return contextManager.NSManager.LookupPrefix (ns);
+ }
+
+ public string LookupPrefix (string ns, bool atomized)
+ {
+ return contextManager.NSManager.LookupPrefix (ns, atomized);
+ }
+
+ public string LookupNamespace (string prefix)
+ {
+ return contextManager.NSManager.LookupNamespace (prefix);
+ }
+
+ public string LookupNamespace (string prefix, bool atomized)
+ {
+ return contextManager.NSManager.LookupNamespace (prefix, atomized);
+ }
+
+ public IDictionary GetNamespacesInScope (XmlNamespaceScope scope)
+ {
+ return contextManager.NSManager.GetNamespacesInScope (scope);
+ }
+ #endregion
+ }
+}
+
+#endif
diff --git a/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XQueryConvert.cs b/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XQueryConvert.cs
new file mode 100755
index 00000000000..6e1109c5aef
--- /dev/null
+++ b/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XQueryConvert.cs
@@ -0,0 +1,1021 @@
+//
+// System.Xml.Query.XQueryConvert
+//
+// Author:
+// Atsushi Enomoto <atsushi@ximian.com>
+//
+// Copyright (C) 2004 Novell Inc.
+//
+
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+#if NET_2_0
+
+using System;
+using System.Globalization;
+using System.IO;
+using System.Text;
+using System.Xml;
+using System.Xml.Schema;
+using System.Xml.XPath;
+
+namespace System.Xml
+{
+ internal class XQueryConvert // Won't be public in the final stage
+ {
+ [MonoTODO]
+ public static bool ShouldCheckValueFacets (XmlSchemaType schemaTypeDest)
+ {
+ throw new NotImplementedException ();
+ }
+
+ public static XmlTypeCode GetFallbackType (XmlTypeCode type)
+ {
+ switch (type) {
+ case XmlTypeCode.AnyAtomicType:
+ return XmlTypeCode.Item;
+ case XmlTypeCode.UntypedAtomic:
+ return XmlTypeCode.String;
+ case XmlTypeCode.Notation:
+ return XmlTypeCode.QName;
+ case XmlTypeCode.NormalizedString:
+ case XmlTypeCode.Token:
+ case XmlTypeCode.Language:
+ case XmlTypeCode.NmToken:
+ case XmlTypeCode.Name:
+ case XmlTypeCode.NCName:
+ case XmlTypeCode.Id:
+ case XmlTypeCode.Idref:
+ case XmlTypeCode.Entity:
+ return XmlTypeCode.String;
+ case XmlTypeCode.NonPositiveInteger:
+ return XmlTypeCode.Decimal;
+ case XmlTypeCode.NegativeInteger:
+ return XmlTypeCode.NonPositiveInteger;
+ case XmlTypeCode.Long:
+ return XmlTypeCode.Integer;
+ case XmlTypeCode.Short:
+ return XmlTypeCode.Int;
+ case XmlTypeCode.Byte:
+ return XmlTypeCode.Int;
+ case XmlTypeCode.NonNegativeInteger:
+ return XmlTypeCode.Decimal;
+ case XmlTypeCode.UnsignedLong:
+ return XmlTypeCode.NonNegativeInteger;
+ case XmlTypeCode.UnsignedInt:
+ return XmlTypeCode.Integer;
+ case XmlTypeCode.UnsignedShort:
+ return XmlTypeCode.Int;
+ case XmlTypeCode.UnsignedByte:
+ return XmlTypeCode.UnsignedShort;
+ case XmlTypeCode.PositiveInteger:
+ return XmlTypeCode.NonNegativeInteger;
+ default:
+ return XmlTypeCode.None;
+ }
+ }
+
+ [MonoTODO]
+ // See XQuery & XPath 2.0 functions & operators section 17.
+ public static bool CanConvert (XPathItem item, XmlSchemaType schemaTypeDest)
+ {
+ if (item == null)
+ throw new ArgumentNullException ("item");
+ if (schemaTypeDest == null)
+ throw new ArgumentNullException ("schemaTypeDest");
+ XmlTypeCode src = item.XmlType.TypeCode;
+ XmlTypeCode dst = schemaTypeDest.TypeCode;
+
+ // Notation cannot be converted from other than Notation
+ if (src == XmlTypeCode.Notation && dst != XmlTypeCode.Notation)
+ return false;
+
+ // untypedAtomic and string are convertable unless source type is QName.
+ switch (dst) {
+ case XmlTypeCode.UntypedAtomic:
+ case XmlTypeCode.String:
+ return src != XmlTypeCode.QName;
+ }
+
+ switch (src) {
+ case XmlTypeCode.None:
+ case XmlTypeCode.Item:
+ case XmlTypeCode.Node:
+ case XmlTypeCode.Document:
+ case XmlTypeCode.Element:
+ case XmlTypeCode.Attribute:
+ case XmlTypeCode.Namespace:
+ case XmlTypeCode.ProcessingInstruction:
+ case XmlTypeCode.Comment:
+ case XmlTypeCode.Text:
+ throw new NotImplementedException (); // FIXME: check what happens
+
+ case XmlTypeCode.AnyAtomicType:
+ throw new NotImplementedException (); // FIXME: check what happens
+ case XmlTypeCode.UntypedAtomic:
+ case XmlTypeCode.String:
+ // 'M'
+ throw new NotImplementedException (); // FIXME: check what happens
+
+ case XmlTypeCode.Boolean:
+ case XmlTypeCode.Decimal:
+ switch (dst) {
+ case XmlTypeCode.Float:
+ case XmlTypeCode.Double:
+ case XmlTypeCode.Decimal:
+ case XmlTypeCode.Boolean:
+ return true;
+ }
+ return false;
+
+ case XmlTypeCode.Float:
+ case XmlTypeCode.Double:
+ if (dst == XmlTypeCode.Decimal)
+ // 'M'
+ throw new NotImplementedException (); // FIXME: check what happens
+ goto case XmlTypeCode.Decimal;
+
+ case XmlTypeCode.Duration:
+ switch (dst) {
+ case XmlTypeCode.Duration:
+ case XmlTypeCode.YearMonthDuration:
+ case XmlTypeCode.DayTimeDuration:
+ return true;
+ }
+ return false;
+
+ case XmlTypeCode.DateTime:
+ switch (dst) {
+ case XmlTypeCode.DateTime:
+ case XmlTypeCode.Time:
+ case XmlTypeCode.Date:
+ case XmlTypeCode.GYearMonth:
+ case XmlTypeCode.GYear:
+ case XmlTypeCode.GMonthDay:
+ case XmlTypeCode.GDay:
+ case XmlTypeCode.GMonth:
+ return true;
+ }
+ return false;
+
+ case XmlTypeCode.Time:
+ switch (dst) {
+ case XmlTypeCode.Time:
+ case XmlTypeCode.Date:
+ return true;
+ }
+ return false;
+
+ case XmlTypeCode.Date:
+ if (dst == XmlTypeCode.Time)
+ return false;
+ goto case XmlTypeCode.DateTime;
+
+ case XmlTypeCode.GYearMonth:
+ case XmlTypeCode.GYear:
+ case XmlTypeCode.GMonthDay:
+ case XmlTypeCode.GDay:
+ case XmlTypeCode.GMonth:
+ return src == dst;
+
+ case XmlTypeCode.HexBinary:
+ case XmlTypeCode.Base64Binary:
+ if (src == dst)
+ return true;
+ switch (dst) {
+ case XmlTypeCode.HexBinary:
+ case XmlTypeCode.Base64Binary:
+ return true;
+ }
+ return false;
+
+ case XmlTypeCode.AnyUri:
+ case XmlTypeCode.QName:
+ case XmlTypeCode.Notation:
+ return src == dst;
+
+ case XmlTypeCode.NormalizedString:
+ case XmlTypeCode.Token:
+ case XmlTypeCode.Language:
+ case XmlTypeCode.NmToken:
+ case XmlTypeCode.Name:
+ case XmlTypeCode.NCName:
+ case XmlTypeCode.Id:
+ case XmlTypeCode.Idref:
+ case XmlTypeCode.Entity:
+ case XmlTypeCode.Integer:
+ case XmlTypeCode.NonPositiveInteger:
+ case XmlTypeCode.NegativeInteger:
+ case XmlTypeCode.Long:
+ case XmlTypeCode.Int:
+ case XmlTypeCode.Short:
+ case XmlTypeCode.Byte:
+ case XmlTypeCode.NonNegativeInteger:
+ case XmlTypeCode.UnsignedLong:
+ case XmlTypeCode.UnsignedInt:
+ case XmlTypeCode.UnsignedShort:
+ case XmlTypeCode.UnsignedByte:
+ case XmlTypeCode.PositiveInteger:
+ throw new NotImplementedException ();
+
+ // xdt:*
+ case XmlTypeCode.YearMonthDuration:
+ if (dst == XmlTypeCode.DayTimeDuration)
+ return false;
+ goto case XmlTypeCode.Duration;
+ case XmlTypeCode.DayTimeDuration:
+ if (dst == XmlTypeCode.YearMonthDuration)
+ return false;
+ goto case XmlTypeCode.Duration;
+ }
+
+ throw new NotImplementedException ();
+ }
+
+ // Individual conversion
+
+ public static string AnyUriToString (string value)
+ {
+ return value;
+ }
+
+ public static byte [] Base64BinaryToHexBinary (byte [] value)
+ {
+ return XmlConvert.FromBinHexString (Convert.ToBase64String (value));
+ }
+
+ public static string Base64BinaryToString (byte [] value)
+ {
+ return Convert.ToBase64String (value);
+ }
+
+ public static decimal BooleanToDecimal (bool value)
+ {
+ return Convert.ToDecimal (value);
+ }
+
+ public static double BooleanToDouble (bool value)
+ {
+ return Convert.ToDouble (value);
+ }
+
+ public static float BooleanToFloat (bool value)
+ {
+ return Convert.ToSingle (value);
+ }
+
+ public static int BooleanToInt (bool value)
+ {
+ return Convert.ToInt32 (value);
+ }
+
+ public static long BooleanToInteger (bool value)
+ {
+ return Convert.ToInt64 (value);
+ }
+
+ public static string BooleanToString (bool value)
+ {
+ // It looks not returning "True"
+ return value ? "true" : "false";
+ }
+
+ [MonoTODO]
+ public static DateTime DateTimeToDate (DateTime value)
+ {
+ return value.Date;
+ }
+
+ [MonoTODO]
+ public static DateTime DateTimeToGDay (DateTime value)
+ {
+ return new DateTime (0, 0, value.Day);
+ }
+
+ [MonoTODO]
+ public static DateTime DateTimeToGMonth (DateTime value)
+ {
+ return new DateTime (0, value.Month, 0);
+ }
+
+ [MonoTODO]
+ public static DateTime DateTimeToGYear (DateTime value)
+ {
+ return new DateTime (value.Year, 0, 0);
+ }
+
+ [MonoTODO]
+ public static DateTime DateTimeToGYearMonth (DateTime value)
+ {
+ return new DateTime (value.Year, value.Month, 0);
+ }
+
+ [MonoTODO]
+ public static DateTime DateToDateTime (DateTime value)
+ {
+ return value.Date;
+ }
+
+ [MonoTODO]
+ public static DateTime DateToGDay (DateTime value)
+ {
+ return new DateTime (0, 0, value.Day);
+ }
+
+ [MonoTODO]
+ public static DateTime DateToGMonth (DateTime value)
+ {
+ return new DateTime (0, value.Month, 0);
+ }
+
+ [MonoTODO]
+ public static DateTime DateToGYear (DateTime value)
+ {
+ return new DateTime (value.Year, 0, 0);
+ }
+
+ [MonoTODO]
+ public static DateTime DateToGYearMonth (DateTime value)
+ {
+ return new DateTime (value.Year, value.Month, 0);
+ }
+
+ [MonoTODO]
+ public static string DateToString (DateTime value)
+ {
+ return XmlConvert.ToString (value);
+ }
+
+ [MonoTODO]
+ public static string DateTimeToString (DateTime value)
+ {
+ return XmlConvert.ToString (value);
+ }
+
+ [MonoTODO]
+ public static string DayTimeDurationToDuration (TimeSpan value)
+ {
+ return XmlConvert.ToString (value);
+ }
+
+ [MonoTODO]
+ public static string DayTimeDurationToString (TimeSpan value)
+ {
+ return DayTimeDurationToDuration (value);
+ }
+
+ [MonoTODO]
+ public static bool DecimalToBoolean (decimal value)
+ {
+ return value != 0;
+ }
+
+ [MonoTODO]
+ public static double DecimalToDouble (decimal value)
+ {
+ return (double) value;
+ }
+
+ [MonoTODO]
+ public static float DecimalToFloat (decimal value)
+ {
+ return (float) value;
+ }
+
+ [MonoTODO]
+ public static int DecimalToInt (decimal value)
+ {
+ return (int) value;
+ }
+
+ [MonoTODO]
+ public static long DecimalToInteger (decimal value)
+ {
+ return (long) value;
+ }
+
+ [MonoTODO] // what if value was negative?
+ public static decimal DecimalToNonNegativeInteger (decimal value)
+ {
+ throw new NotImplementedException ();
+ }
+
+ [MonoTODO] // what if value was positive?
+ public static decimal DecimalToNonPositiveInteger (decimal value)
+ {
+ throw new NotImplementedException ();
+ }
+
+ [MonoTODO]
+ public static string DecimalToString (decimal value)
+ {
+ return XmlConvert.ToString (value);
+ }
+
+ [MonoTODO]
+ public static bool DoubleToBoolean (double value)
+ {
+ return value != 0;
+ }
+
+ [MonoTODO]
+ public static decimal DoubleToDecimal (double value)
+ {
+ return (decimal) value;
+ }
+
+ [MonoTODO]
+ public static float DoubleToFloat (double value)
+ {
+ return (float) value;
+ }
+
+ [MonoTODO]
+ public static int DoubleToInt (double value)
+ {
+ return (int) value;
+ }
+
+ [MonoTODO]
+ public static long DoubleToInteger (double value)
+ {
+ return (long) value;
+ }
+
+ [MonoTODO] // what if value was negative?
+ public static decimal DoubleToNonNegativeInteger (double value)
+ {
+ throw new NotImplementedException ();
+ }
+
+ [MonoTODO] // what if value was positive?
+ public static decimal DoubleToNonPositiveInteger (double value)
+ {
+ throw new NotImplementedException ();
+ }
+
+ [MonoTODO]
+ public static string DoubleToString (double value)
+ {
+ return XmlConvert.ToString (value);
+ }
+
+ [MonoTODO]
+ public static TimeSpan DurationToDayTimeDuration (string value)
+ {
+ return XmlConvert.ToTimeSpan (value);
+ }
+
+ [MonoTODO]
+ public static string DurationToString (string value)
+ {
+ return XmlConvert.ToString (XmlConvert.ToTimeSpan (value));
+ }
+
+ [MonoTODO]
+ public static TimeSpan DurationToYearMonthDuration (string value)
+ {
+ return XmlConvert.ToTimeSpan (value);
+ }
+
+
+ [MonoTODO]
+ public static bool FloatToBoolean (float value)
+ {
+ return value != 0;
+ }
+
+ [MonoTODO]
+ public static decimal FloatToDecimal (float value)
+ {
+ return (decimal) value;
+ }
+
+ [MonoTODO]
+ public static double FloatToDouble (float value)
+ {
+ return (double) value;
+ }
+
+ [MonoTODO]
+ public static int FloatToInt (float value)
+ {
+ return (int) value;
+ }
+
+ [MonoTODO]
+ public static long FloatToInteger (float value)
+ {
+ return (long) value;
+ }
+
+ [MonoTODO] // what if value was negative?
+ public static decimal FloatToNonNegativeInteger (float value)
+ {
+ throw new NotImplementedException ();
+ }
+
+ [MonoTODO] // what if value was positive?
+ public static decimal FloatToNonPositiveInteger (float value)
+ {
+ throw new NotImplementedException ();
+ }
+
+ [MonoTODO]
+ public static string FloatToString (float value)
+ {
+ return XmlConvert.ToString (value);
+ }
+
+ [MonoTODO]
+ public static string GDayToString (DateTime value)
+ {
+ return XmlConvert.ToString (TimeSpan.FromDays (value.Day));
+ }
+
+ [MonoTODO]
+ public static string GMonthDayToString (DateTime value)
+ {
+ return XmlConvert.ToString (new TimeSpan (value.Day, value.Hour, value.Minute, value.Second));
+ }
+
+ [MonoTODO]
+ public static string GMonthToString (DateTime value)
+ {
+ return XmlConvert.ToString (new TimeSpan (0, value.Month, 0));
+ }
+
+ [MonoTODO]
+ public static string GYearMonthToString (DateTime value)
+ {
+ return XmlConvert.ToString (new TimeSpan (value.Year, value.Month, 0));
+ }
+
+ [MonoTODO]
+ public static string GYearToString (DateTime value)
+ {
+ return XmlConvert.ToString (new TimeSpan (new DateTime (value.Year, 0, 0).Ticks));
+ }
+
+ public static string HexBinaryToString (byte [] data)
+ {
+ return XmlConvert.ToBinHexString (data);
+ }
+
+ public static string HexBinaryToBase64String (byte [] data)
+ {
+ return XmlConvert.ToBinHexString (data);
+ }
+
+
+ [MonoTODO]
+ public static bool IntegerToBoolean (long value)
+ {
+ return value != 0;
+ }
+
+ [MonoTODO]
+ public static decimal IntegerToDecimal (long value)
+ {
+ return (decimal) value;
+ }
+
+ [MonoTODO]
+ public static double IntegerToDouble (long value)
+ {
+ return (double) value;
+ }
+
+ [MonoTODO]
+ public static float IntegerToFloat (long value)
+ {
+ return (float) value;
+ }
+
+ [MonoTODO]
+ public static int IntegerToInt (long value)
+ {
+ return (int) value;
+ }
+
+ [MonoTODO]
+ public static string IntegerToString (long value)
+ {
+ return XmlConvert.ToString (value);
+ }
+
+ [MonoTODO]
+ public static bool IntToBoolean (int value)
+ {
+ return value != 0;
+ }
+
+ [MonoTODO]
+ public static decimal IntToDecimal (int value)
+ {
+ return (decimal) value;
+ }
+
+ [MonoTODO]
+ public static double IntToDouble (int value)
+ {
+ return (double) value;
+ }
+
+ [MonoTODO]
+ public static float IntToFloat (int value)
+ {
+ return (float) value;
+ }
+
+ [MonoTODO]
+ public static long IntToInteger (int value)
+ {
+ return (long) value;
+ }
+
+ [MonoTODO]
+ public static string IntToString (int value)
+ {
+ return XmlConvert.ToString (value);
+ }
+
+ [MonoTODO]
+ public static string NonNegativeIntegerToString (decimal value)
+ {
+ return XmlConvert.ToString (value);
+ }
+
+ [MonoTODO]
+ public static string NonPositiveIntegerToString (decimal value)
+ {
+ return XmlConvert.ToString (value);
+ }
+
+ [MonoTODO]
+ public static DateTime TimeToDateTime (DateTime value)
+ {
+ return value;
+ }
+
+ [MonoTODO]
+ public static string TimeToString (DateTime value)
+ {
+ return XmlConvert.ToString (value, "HH:mm:ssZ");
+ }
+
+ [MonoTODO]
+ public static string YearMonthDurationToDuration (TimeSpan value)
+ {
+ return XmlConvert.ToString (value);
+ }
+
+ [MonoTODO]
+ public static string YearMonthDurationToString (TimeSpan value)
+ {
+ return YearMonthDurationToDuration (value);
+ }
+
+ [MonoTODO]
+ public static string StringToAnyUri (string value)
+ {
+ return value;
+ }
+
+ [MonoTODO]
+ public static byte [] StringToBase64Binary (string value)
+ {
+ return Convert.FromBase64String (value);
+ }
+
+ [MonoTODO]
+ public static bool StringToBoolean (string value)
+ {
+ return XmlConvert.ToBoolean (value);
+ }
+
+ [MonoTODO]
+ public static DateTime StringToDate (string value)
+ {
+ return XmlConvert.ToDateTime (value);
+ }
+
+ [MonoTODO]
+ public static DateTime StringToDateTime (string value)
+ {
+ return XmlConvert.ToDateTime (value);
+ }
+
+ [MonoTODO]
+ public static TimeSpan StringToDayTimeDuration (string value)
+ {
+ return XmlConvert.ToTimeSpan (value);
+ }
+
+ [MonoTODO]
+ public static decimal StringToDecimal (string value)
+ {
+ return XmlConvert.ToDecimal (value);
+ }
+
+ [MonoTODO]
+ public static double StringToDouble (string value)
+ {
+ return XmlConvert.ToDouble (value);
+ }
+
+ [MonoTODO]
+ public static string StringToDuration (string value)
+ {
+ return XmlConvert.ToString (XmlConvert.ToTimeSpan (value));
+ }
+
+ [MonoTODO]
+ public static float StringToFloat (string value)
+ {
+ return XmlConvert.ToSingle (value);
+ }
+
+ [MonoTODO]
+ public static DateTime StringToGDay (string value)
+ {
+ return XmlConvert.ToDateTime (value);
+ }
+
+ [MonoTODO]
+ public static DateTime StringToGMonth (string value)
+ {
+ return XmlConvert.ToDateTime (value);
+ }
+
+ [MonoTODO]
+ public static DateTime StringToGMonthDay (string value)
+ {
+ return XmlConvert.ToDateTime (value);
+ }
+
+ [MonoTODO]
+ public static DateTime StringToGYear (string value)
+ {
+ return XmlConvert.ToDateTime (value);
+ }
+
+ [MonoTODO]
+ public static DateTime StringToGYearMonth (string value)
+ {
+ return XmlConvert.ToDateTime (value);
+ }
+
+ [MonoTODO]
+ public static byte [] StringToHexBinary (string value)
+ {
+ return XmlConvert.FromBinHexString (value);
+ }
+
+ [MonoTODO]
+ public static int StringToInt (string value)
+ {
+ return XmlConvert.ToInt32 (value);
+ }
+
+ [MonoTODO]
+ public static long StringToInteger (string value)
+ {
+ return XmlConvert.ToInt64 (value);
+ }
+
+ [MonoTODO]
+ public static decimal StringToNonNegativeInteger (string value)
+ {
+ return XmlConvert.ToDecimal (value);
+ }
+
+ [MonoTODO]
+ public static decimal StringToNonPositiveInteger (string value)
+ {
+ return XmlConvert.ToDecimal (value);
+ }
+
+ [MonoTODO]
+ public static DateTime StringToTime (string value)
+ {
+ return XmlConvert.ToDateTime (value);
+ }
+
+ [MonoTODO]
+ public static long StringToUnsignedInt (string value)
+ {
+ return XmlConvert.ToInt32 (value);
+ }
+
+ [MonoTODO]
+ public static decimal StringToUnsignedLong (string value)
+ {
+ return XmlConvert.ToInt32 (value);
+ }
+
+ [MonoTODO]
+ public static int StringToUnsignedShort (string value)
+ {
+ return XmlConvert.ToInt32 (value);
+ }
+
+ [MonoTODO]
+ public static TimeSpan StringToYearMonthDuration (string value)
+ {
+ return XmlConvert.ToTimeSpan (value);
+ }
+
+ [MonoTODO]
+ public static string ItemToAnyUri (XPathItem value)
+ {
+ return value.Value;
+ }
+
+ [MonoTODO]
+ public static byte [] ItemToBase64Binary (XPathItem value)
+ {
+ return Convert.FromBase64String (value.Value);
+ }
+
+ [MonoTODO]
+ public static bool ItemToBoolean (XPathItem value)
+ {
+ return XmlConvert.ToBoolean (value.Value);
+ }
+
+ [MonoTODO]
+ public static DateTime ItemToDate (XPathItem value)
+ {
+ return XmlConvert.ToDateTime (value.Value);
+ }
+
+ [MonoTODO]
+ public static DateTime ItemToDateTime (XPathItem value)
+ {
+ return XmlConvert.ToDateTime (value.Value);
+ }
+
+ [MonoTODO]
+ public static TimeSpan ItemToDayTimeDuration (XPathItem value)
+ {
+ return XmlConvert.ToTimeSpan (value.Value);
+ }
+
+ [MonoTODO]
+ public static decimal ItemToDecimal (XPathItem value)
+ {
+ return XmlConvert.ToDecimal (value.Value);
+ }
+
+ [MonoTODO]
+ public static double ItemToDouble (XPathItem value)
+ {
+ return XmlConvert.ToDouble (value.Value);
+ }
+
+ [MonoTODO]
+ public static string ItemToDuration (XPathItem value)
+ {
+ return XmlConvert.ToString (XmlConvert.ToTimeSpan (value.Value));
+ }
+
+ [MonoTODO]
+ public static float ItemToFloat (XPathItem value)
+ {
+ return XmlConvert.ToSingle (value.Value);
+ }
+
+ [MonoTODO]
+ public static DateTime ItemToGDay (XPathItem value)
+ {
+ return XmlConvert.ToDateTime (value.Value);
+ }
+
+ [MonoTODO]
+ public static DateTime ItemToGMonth (XPathItem value)
+ {
+ return XmlConvert.ToDateTime (value.Value);
+ }
+
+ [MonoTODO]
+ public static DateTime ItemToGMonthDay (XPathItem value)
+ {
+ return XmlConvert.ToDateTime (value.Value);
+ }
+
+ [MonoTODO]
+ public static DateTime ItemToGYear (XPathItem value)
+ {
+ return XmlConvert.ToDateTime (value.Value);
+ }
+
+ [MonoTODO]
+ public static DateTime ItemToGYearMonth (XPathItem value)
+ {
+ return XmlConvert.ToDateTime (value.Value);
+ }
+
+ [MonoTODO]
+ public static byte [] ItemToHexBinary (XPathItem value)
+ {
+ return XmlConvert.FromBinHexString (value.Value);
+ }
+
+ [MonoTODO]
+ public static int ItemToInt (XPathItem value)
+ {
+ return XmlConvert.ToInt32 (value.Value);
+ }
+
+ [MonoTODO]
+ public static long ItemToInteger (XPathItem value)
+ {
+ return XmlConvert.ToInt64 (value.Value);
+ }
+
+ [MonoTODO]
+ public static XPathItem ItemToItem (XPathItem value, XmlSchemaType schemaTypeDest)
+ {
+ return new XPathAtomicValue (value.Value, schemaTypeDest);
+ }
+
+ [MonoTODO]
+ public static decimal ItemToNonNegativeInteger (XPathItem value)
+ {
+ return XmlConvert.ToDecimal (value.Value);
+ }
+
+ [MonoTODO]
+ public static decimal ItemToNonPositiveInteger (XPathItem value)
+ {
+ return XmlConvert.ToDecimal (value.Value);
+ }
+
+ [MonoTODO]
+ public static XmlQualifiedName ItemToQName (XPathItem value)
+ {
+ return (XmlQualifiedName) value.TypedValue;
+ }
+
+ [MonoTODO]
+ public static string ItemToString (XPathItem value)
+ {
+ if (value.ValueType == typeof (DateTime))
+ return XmlConvert.ToString ((DateTime) value.TypedValue);
+ if (value.TypedValue is XmlQualifiedName)
+ throw new ArgumentException ("Invalid cast from schema QName type to string type.");
+ return value.Value;
+ }
+
+ [MonoTODO]
+ public static DateTime ItemToTime (XPathItem value)
+ {
+ return XmlConvert.ToDateTime (value.Value);
+ }
+
+ [MonoTODO]
+ public static long ItemToUnsignedInt (XPathItem value)
+ {
+ return XmlConvert.ToInt32 (value.Value);
+ }
+
+ [MonoTODO]
+ public static decimal ItemToUnsignedLong (XPathItem value)
+ {
+ return XmlConvert.ToInt32 (value.Value);
+ }
+
+ [MonoTODO]
+ public static int ItemToUnsignedShort (XPathItem value)
+ {
+ return XmlConvert.ToInt32 (value.Value);
+ }
+
+ [MonoTODO]
+ public static TimeSpan ItemToYearMonthDuration (XPathItem value)
+ {
+ return XmlConvert.ToTimeSpan (value.Value);
+ }
+ }
+}
+
+#endif
diff --git a/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XQueryDefaultFunctionCall.cs b/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XQueryDefaultFunctionCall.cs
new file mode 100755
index 00000000000..7eb4e280563
--- /dev/null
+++ b/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XQueryDefaultFunctionCall.cs
@@ -0,0 +1,387 @@
+//
+// XQueryDefaultFunctionCall.cs
+//
+// Author:
+// Atsushi Enomoto <atsushi@ximian.com>
+//
+//
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+//
+// XQuery 1.0 and XPath 2.0 Functions implementation as XPathItemExpression.
+// See XQuery 1.0 and XPath 2.0 Functions and Operators.
+//
+#if NET_2_0
+using System;
+using System.Collections;
+using System.Reflection;
+using System.Xml;
+using System.Xml.Schema;
+using System.Xml.Query;
+using System.Xml.XPath;
+using System.Xml.Xsl;
+
+namespace Mono.Xml.XPath2
+{
+ internal abstract class DefaultFunctionCall : FunctionCallExprBase
+ {
+ static Hashtable qnameTable = new Hashtable ();
+ static XmlQualifiedName GetName (string name)
+ {
+ XmlQualifiedName qname = qnameTable [name] as XmlQualifiedName;
+ if (qname == null) {
+ qname = new XmlQualifiedName (name, XQueryFunction.Namespace);
+ qnameTable.Add (name, qname);
+ }
+ return qname;
+ }
+
+ public DefaultFunctionCall (XQueryStaticContext ctx, string name, int minArgs, int maxArgs, SequenceType type, ExprSequence args)
+ : base (GetName (name), args)
+ {
+ this.type = type;
+ this.minArgs = minArgs;
+ this.maxArgs = maxArgs;
+ }
+
+ SequenceType type;
+ int minArgs;
+ int maxArgs;
+
+ public override int MinArgs { get { return minArgs; } }
+ public override int MaxArgs { get { return maxArgs; } }
+
+ public override SequenceType StaticType {
+ get { return type; }
+ }
+ }
+
+ // Accessors
+
+ // 2.1 fn:node-name ($arg as node ()?) as xs:QName?
+ internal class FnNodeNameCall : DefaultFunctionCall
+ {
+ public FnNodeNameCall (XQueryStaticContext ctx, ExprSequence args)
+ : base (ctx, "node-name", 1, 1, SequenceType.Create (XmlSchemaSimpleType.XsQName, Occurence.Optional), args)
+ {
+ }
+
+ public override XPathSequence Evaluate (XPathSequence iter)
+ {
+ XPathSequence res = Args [0].Evaluate (iter);
+ if (!res.MoveNext ())
+ return new XPathEmptySequence (iter.Context);
+ // FIXME: what happens if context item is not a node.
+ XPathNavigator nav = res.Current as XPathNavigator;
+ if (nav == null || nav.LocalName == String.Empty)
+ return new XPathEmptySequence (iter.Context);
+ return new SingleItemIterator (new XPathAtomicValue (new XmlQualifiedName (nav.LocalName, nav.NamespaceURI), XmlSchemaSimpleType.XsQName), iter);
+ }
+ }
+
+ // 2.2 fn:nilled ($arg as node()) as xs:boolean?
+ internal class FnNilledCall : DefaultFunctionCall
+ {
+ public FnNilledCall (XQueryStaticContext ctx, XPathItemExpression [] args)
+ : base (ctx, "nilled", 1, 1, SequenceType.Create (XmlSchemaSimpleType.XsBoolean, Occurence.One), args)
+ {
+ }
+
+ public override XPathSequence Evaluate (XPathSequence iter)
+ {
+ XPathSequence res = Args [0].Evaluate (iter);
+ if (!res.MoveNext ())
+ return new XPathEmptySequence (iter.Context);
+ XPathNavigator nav = res.Current as XPathNavigator;
+ IXmlSchemaInfo info = nav.NodeType == XPathNodeType.Element ? nav.SchemaInfo : null;
+ if (info != null)
+ return new SingleItemIterator (new XPathAtomicValue (info.IsNil, null), iter);
+ else
+ return new XPathEmptySequence (iter.Context);
+ }
+ }
+
+ // 2.3 fn:string ($arg as item()?) as xs:string
+ internal class FnStringCall : DefaultFunctionCall
+ {
+ public FnStringCall (XQueryStaticContext ctx, XPathItemExpression [] args)
+ : base (ctx, "string", 0, 1, SequenceType.Create (XmlSchemaSimpleType.XsString, Occurence.Optional), args)
+ {
+ }
+
+ public override XPathSequence Evaluate (XPathSequence iter)
+ {
+ XPathItem item = null;
+ if (Args.Length == 0)
+ item = iter.Context.CurrentItem;
+ else {
+ XPathSequence res = Args [0].Evaluate (iter);
+ if (!res.MoveNext ())
+ return new XPathEmptySequence (iter.Context);
+ item = res.Current;
+ }
+ return new SingleItemIterator (new XPathAtomicValue (Core (item), null), iter);
+ }
+
+ private string Core (XPathItem item)
+ {
+ XPathNavigator nav = item as XPathNavigator;
+
+ return nav != null ? nav.Value : XQueryConvert.ItemToString (item);
+ }
+ }
+
+ // 2.4 fn:data ($arg as item()*) as xdt:anyAtomicType*
+ internal class FnDataCall : DefaultFunctionCall
+ {
+ public FnDataCall (XQueryStaticContext ctx, XPathItemExpression [] args)
+ : base (ctx, "data", 1, 1, SequenceType.Create (XmlSchemaComplexType.AnyType, Occurence.ZeroOrMore), args)
+ {
+ }
+
+ public override XPathSequence Evaluate (XPathSequence iter)
+ {
+ return new AtomizingIterator (Args [0].Evaluate (iter));
+ }
+ }
+
+ // 2.5 fn:base-uri ($arg as node()?) as xs:anyURI?
+ internal class FnBaseUriCall : DefaultFunctionCall
+ {
+ public FnBaseUriCall (XQueryStaticContext ctx, XPathItemExpression [] args)
+ : base (ctx, "base-uri", 1, 1, SequenceType.Create (XmlSchemaSimpleType.XsAnyUri, Occurence.Optional), args)
+ {
+ }
+
+ public override XPathSequence Evaluate (XPathSequence iter)
+ {
+ XPathSequence res = Args [0].Evaluate (iter);
+ if (res.MoveNext ())
+ return new XPathEmptySequence (iter.Context);
+ XPathNavigator nav = res.Current as XPathNavigator;
+ if (nav == null)
+ return new XPathEmptySequence (iter.Context);
+ else
+ return new SingleItemIterator (new XPathAtomicValue (nav.BaseURI, XmlSchemaSimpleType.XsString), iter);
+ }
+ }
+
+ // 2.6 fn:document-uri ($arg as node()?) as xs:anyURI?
+ internal class FnDocumentUriCall : DefaultFunctionCall
+ {
+ public FnDocumentUriCall (XQueryStaticContext ctx, XPathItemExpression [] args)
+ : base (ctx, "document-uri", 1, 1, SequenceType.Create (XmlSchemaSimpleType.XsAnyUri, Occurence.Optional), args)
+ {
+ }
+
+ public override XPathSequence Evaluate (XPathSequence iter)
+ {
+ XPathSequence res = Args [0].Evaluate (iter);
+ if (res.MoveNext ())
+ return new XPathEmptySequence (iter.Context);
+ XPathNavigator nav = res.Current as XPathNavigator;
+ if (nav == null)
+ return new XPathEmptySequence (iter.Context);
+ nav = nav.Clone ();
+ nav.MoveToRoot ();
+ return new SingleItemIterator (new XPathAtomicValue (nav.BaseURI, null), iter);
+ }
+ }
+
+ // 3 fn:error ()
+ // fn:error ($error as xs:QName)
+ // fn:error ($error as xs:QName, $description as xs:string)
+ // fn:error ($error as xs:QName, $description as xs:string, $error-object as item()*)
+ internal class FnErrorCall : DefaultFunctionCall
+ {
+ public FnErrorCall (XQueryStaticContext ctx, XPathItemExpression [] args)
+ // FIXME: return type is actually none
+ : base (ctx, "error", 0, 3, SequenceType.AnyType, args)
+ {
+ }
+
+ public override XPathSequence Evaluate (XPathSequence iter)
+ {
+ // error name
+ XPathSequence errorNameIter = Args.Length > 0 ? Args [0].Evaluate (iter) : null;
+ XmlQualifiedName errorType = XmlQualifiedName.Empty;
+ if (errorNameIter != null && errorNameIter.MoveNext ())
+ errorType = XQueryConvert.ItemToQName (errorNameIter.Current);
+
+ // description
+ string description = Args.Length > 1 ? Args [1].EvaluateAsString (iter) : String.Empty;
+
+ // error-object
+ XPathSequence errorObjIter = Args.Length > 2 ? Args [2].Evaluate (iter) : null;
+
+ // FIXME: add error-object information
+ throw new XmlQueryException (errorType + description);
+ }
+ }
+
+ // 4 trace ($value as item()*, $label as xs:string) as item()*
+ internal class FnTraceCall : DefaultFunctionCall
+ {
+ public FnTraceCall (XQueryStaticContext ctx, XPathItemExpression [] args)
+ : base (ctx, "trace", 2, 2, SequenceType.Create (XmlSchemaComplexType.AnyType, Occurence.ZeroOrMore), args)
+ {
+ }
+
+ public override XPathSequence Evaluate (XPathSequence iter)
+ {
+ return new TracingIterator (Args [0].Evaluate (iter), Args [1].EvaluateAsString (iter));
+ }
+ }
+
+ // 5 constructor functions
+ internal class AtomicConstructorCall : DefaultFunctionCall
+ {
+ // FIXME: use IXmlNamespaceResolver.LookupPrefix() in ctx
+ public AtomicConstructorCall (XQueryStaticContext ctx, SequenceType type, XPathItemExpression [] args)
+ : base (ctx, type.SchemaType.QualifiedName.Name, 1, 1, type, args)
+ {
+ }
+
+ public override XPathSequence Evaluate (XPathSequence iter)
+ {
+ return new SingleItemIterator (XQueryConvert.ItemToItem (Atomize (Args [0].Evaluate (iter)), null), iter);
+ }
+ }
+
+ // 6 functions on numerics (operators are not defined here)
+
+ // 6.4.1 fn:abs ($arg as numeric?) as numeric?
+ internal class FnAbsCall : DefaultFunctionCall
+ {
+ public FnAbsCall (XQueryStaticContext ctx, XPathItemExpression [] args)
+ : base (ctx, "abs", 1, 1, args [0].StaticType, args)
+ {
+ }
+
+ public override XPathSequence Evaluate (XPathSequence iter)
+ {
+ XPathSequence arg = Args [0].Evaluate (iter);
+ if (!arg.MoveNext ())
+ return new XPathEmptySequence (iter.Context);
+ XPathAtomicValue a = null;
+ // FIXME: use schema type IsDerivedFrom()
+ switch (Type.GetTypeCode (arg.Current.ValueType)) {
+ case TypeCode.Int64:
+ return new SingleItemIterator (new XPathAtomicValue (System.Math.Abs (arg.Current.ValueAsInt64), arg.Current.XmlType), iter);
+ case TypeCode.Int32:
+ return new SingleItemIterator (new XPathAtomicValue (System.Math.Abs (arg.Current.ValueAsInt32), arg.Current.XmlType), iter);
+ case TypeCode.Double:
+ return new SingleItemIterator (new XPathAtomicValue (System.Math.Abs (arg.Current.ValueAsDouble), arg.Current.XmlType), iter);
+ case TypeCode.Decimal:
+ return new SingleItemIterator (new XPathAtomicValue (System.Math.Abs (arg.Current.ValueAsDecimal), arg.Current.XmlType), iter);
+ case TypeCode.Single:
+ return new SingleItemIterator (new XPathAtomicValue (System.Math.Abs (arg.Current.ValueAsSingle), arg.Current.XmlType), iter);
+ }
+ return new XPathEmptySequence (iter.Context);
+ }
+ }
+
+ // 6.4.2 fn:ceiling ($arg as numeric?) as numeric?
+ internal class FnCeilingCall : DefaultFunctionCall
+ {
+ public FnCeilingCall (XQueryStaticContext ctx, XPathItemExpression [] args)
+ : base (ctx, "ceiling", 1, 1, args [0].StaticType, args)
+ {
+ }
+
+ public override XPathSequence Evaluate (XPathSequence iter)
+ {
+ throw new NotImplementedException ();
+ }
+ }
+
+ // 6.4.3 fn:floor ($arg as numeric?) as numeric?
+ internal class FnFloorCall : DefaultFunctionCall
+ {
+ public FnFloorCall (XQueryStaticContext ctx, XPathItemExpression [] args)
+ : base (ctx, "floor", 1, 1, args [0].StaticType, args)
+ {
+ }
+
+ public override XPathSequence Evaluate (XPathSequence iter)
+ {
+ throw new NotImplementedException ();
+ }
+ }
+
+ // 6.4.4 fn:round ($arg as numeric?) as numeric?
+ internal class FnRoundCall : DefaultFunctionCall
+ {
+ public FnRoundCall (XQueryStaticContext ctx, XPathItemExpression [] args)
+ : base (ctx, "round", 1, 1, args [0].StaticType, args)
+ {
+ }
+
+ public override XPathSequence Evaluate (XPathSequence iter)
+ {
+ throw new NotImplementedException ();
+ }
+ }
+
+ // 6.4.5 fn:round-half-to-even ($arg as numeric?) as numeric?
+ internal class FnRoundHalfToEvenCall : DefaultFunctionCall
+ {
+ public FnRoundHalfToEvenCall (XQueryStaticContext ctx, XPathItemExpression [] args)
+ : base (ctx, "round-half-to-even", 1, 2, args [0].StaticType, args)
+ {
+ }
+
+ public override XPathSequence Evaluate (XPathSequence iter)
+ {
+ throw new NotImplementedException ();
+ }
+ }
+
+ // 7.2.1 fn:codepoints-to-string ($arg as xs:integer*) as xs:string
+ internal class FnCodepointsToStringCall : DefaultFunctionCall
+ {
+ public FnCodepointsToStringCall (XQueryStaticContext ctx, XPathItemExpression [] args)
+ : base (ctx, "codepoints-to-string", 1, 1, SequenceType.IntegerList, args)
+ {
+ }
+
+ public override XPathSequence Evaluate (XPathSequence iter)
+ {
+ throw new NotImplementedException ();
+ }
+ }
+
+ internal class FnStringCallToCodepointsCall : DefaultFunctionCall
+ {
+ public FnStringCallToCodepointsCall (XQueryStaticContext ctx, XPathItemExpression [] args)
+ : base (ctx, "string-to-codepoints", 1, 1, SequenceType.Create (XmlSchemaSimpleType.XsString, Occurence.Optional), args)
+ {
+ }
+
+ public override XPathSequence Evaluate (XPathSequence iter)
+ {
+ throw new NotImplementedException ();
+ }
+ }
+}
+#endif
diff --git a/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XQueryExpression.cs b/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XQueryExpression.cs
new file mode 100755
index 00000000000..fcb6dc00db7
--- /dev/null
+++ b/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XQueryExpression.cs
@@ -0,0 +1,579 @@
+//
+// XQueryExpression.cs - abstract syntax tree for XQuery 1.0
+//
+// Author:
+// Atsushi Enomoto <atsushi@ximian.com>
+//
+//
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+#if NET_2_0
+using System;
+using System.Collections;
+using System.Xml;
+using System.Xml.Query;
+using System.Xml.Schema;
+using System.Xml.XPath;
+using Mono.Xml.XPath2;
+using Mono.Xml;
+
+namespace Mono.Xml.XQuery
+{
+ internal abstract class XmlConstructorExpr : ExprSingle
+ {
+ public XmlConstructorExpr (ExprSequence content)
+ {
+ this.content = content;
+ }
+
+ ExprSequence content;
+
+ public ExprSequence Content {
+ get { return content; }
+ }
+
+#region CompileAndEvaluate
+ internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
+ {
+ if (Content != null)
+ for (int i = 0; i < Content.Count; i++)
+ Content [i] = Content [i].Compile (compiler);
+ return this;
+ }
+
+ public void SerializeContent (XPathSequence iter)
+ {
+ if (Content != null)
+ foreach (ExprSingle expr in Content)
+ expr.Serialize (iter);
+ }
+
+ internal IXmlNamespaceResolver GetNSResolver (XPathSequence iter)
+ {
+ // FIXME: IXmlNamespaceResolver must be constructed
+ // considering 1)static context and 2)in-scope element
+ // construction.
+ return iter.Context;
+ }
+
+ public XPathSequence EvaluateNode (XPathSequence iter)
+ {
+ return EvaluateNode (iter, XPathNodeType.All);
+ }
+
+ public XPathSequence EvaluateNode (XPathSequence iter, XPathNodeType moveAfterCreation)
+ {
+ XmlDocument doc = new XmlDocument ();
+ XmlWriter w = iter.Context.Writer;
+ try {
+ iter.Context.Writer = doc.CreateNavigator ().AppendChild ();
+ Serialize (iter);
+ iter.Context.Writer.Close ();
+ } finally {
+ iter.Context.Writer = w;
+ }
+ XPathNavigator nav = doc.CreateNavigator ();
+ switch (moveAfterCreation) {
+ case XPathNodeType.Attribute:
+ nav.MoveToFirstAttribute ();
+ break;
+ case XPathNodeType.Root:
+ break;
+ default:
+ nav.MoveToFirstChild ();
+ break;
+ }
+ return new SingleItemIterator (nav, iter.Context);
+ }
+#endregion
+ }
+
+ internal class XmlAttrConstructorList : CollectionBase
+ {
+ public XmlAttrConstructorList ()
+ {
+ }
+
+ public void Add (XmlAttrConstructor item)
+ {
+ List.Add (item);
+ }
+
+ public void Insert (int pos, XmlAttrConstructor item)
+ {
+ List.Insert (pos, item);
+ }
+ }
+
+ internal class XmlElemConstructor : XmlConstructorExpr
+ {
+ XmlQualifiedName name;
+ ExprSequence nameExpr;
+
+ public XmlElemConstructor (XmlQualifiedName name, ExprSequence content)
+ : base (content)
+ {
+ this.name = name;
+ }
+
+ public XmlElemConstructor (ExprSequence name, ExprSequence content)
+ : base (content)
+ {
+ this.name = XmlQualifiedName.Empty;
+ this.nameExpr = name;
+ }
+
+ public XmlQualifiedName Name {
+ get { return name; }
+ }
+ public ExprSequence NameExpr {
+ get { return nameExpr; }
+ }
+
+ internal override void CheckReference (XQueryASTCompiler compiler)
+ {
+ if (nameExpr != null)
+ nameExpr.CheckReference (compiler);
+ if (Content != null)
+ Content.CheckReference (compiler);
+ }
+
+#region CompileAndEvaluate
+ internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
+ {
+ if (NameExpr != null)
+ for (int i = 0; i < NameExpr.Count; i++)
+ NameExpr [i] = NameExpr [i].Compile (compiler);
+ if (Content != null)
+ for (int i = 0; i < Content.Count; i++)
+ Content [i] = Content [i].Compile (compiler);
+ return this;
+ }
+
+ // FIXME: can be optimized by checking all items in Expr
+ public override SequenceType StaticType {
+ get { return SequenceType.Element; }
+ }
+
+ public override void Serialize (XPathSequence iter)
+ {
+ XmlQualifiedName name = EvaluateName (iter);
+ XmlWriter w = iter.Context.Writer;
+ w.WriteStartElement (iter.Context.LookupPrefix (name.Namespace), name.Name, name.Namespace);
+ SerializeContent (iter);
+ w.WriteEndElement ();
+ }
+
+ public override XPathSequence Evaluate (XPathSequence iter)
+ {
+ return EvaluateNode (iter);
+ }
+
+ private XmlQualifiedName EvaluateName (XPathSequence iter)
+ {
+ XmlQualifiedName name = Name;
+ if (NameExpr != null) {
+ XPathAtomicValue value = Atomize (new ExprSequenceIterator (iter, NameExpr));
+ IXmlNamespaceResolver res = iter.Context.NSResolver;
+
+ switch (value.XmlType.TypeCode) {
+ case XmlTypeCode.QName:
+ name = (XmlQualifiedName) value.ValueAs (typeof (XmlQualifiedName), res);
+ break;
+ case XmlTypeCode.String:
+ try {
+ name = InternalPool.ParseQName (value.Value, res);
+ } catch (ArgumentException ex) {
+ // FIXME: add more info
+ throw new XmlQueryException (String.Format ("The evaluation result of the name expression could not be resolved as a valid QName. Evaluation result string is '{0}'.", value.Value));
+ }
+ break;
+ default:
+ // FIXME: add more info
+ throw new XmlQueryException ("A name of an element constructor must be resolved to either a QName or string.");
+ }
+ }
+ return name;
+ }
+#endregion
+ }
+
+ internal class XmlAttrConstructor : XmlConstructorExpr
+ {
+ XmlQualifiedName name;
+ ExprSequence nameExpr;
+
+ public XmlAttrConstructor (XmlQualifiedName name, ExprSequence content)
+ : base (content)
+ {
+ this.name = name;
+ }
+
+ public XmlAttrConstructor (ExprSequence name, ExprSequence content)
+ : base (content)
+ {
+ this.nameExpr = name;
+ }
+
+ internal override void CheckReference (XQueryASTCompiler compiler)
+ {
+ if (nameExpr != null)
+ nameExpr.CheckReference (compiler);
+ if (Content != null)
+ Content.CheckReference (compiler);
+ }
+
+#region CompileAndEvaluate
+ internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
+ {
+ if (NameExpr != null)
+ for (int i = 0; i < NameExpr.Count; i++)
+ NameExpr [i] = NameExpr [i].Compile (compiler);
+ if (Content != null)
+ for (int i = 0; i < Content.Count; i++)
+ Content [i] = Content [i].Compile (compiler);
+ return this;
+ }
+
+ public XmlQualifiedName Name {
+ get { return name; }
+ }
+ public ExprSequence NameExpr {
+ get { return nameExpr; }
+ }
+
+ // FIXME: can be optimized by checking all items in Expr
+ public override SequenceType StaticType {
+ get { return SequenceType.Attribute; }
+ }
+
+ public override void Serialize (XPathSequence iter)
+ {
+ XmlQualifiedName name = EvaluateName (iter);
+ XmlWriter w = iter.Context.Writer;
+ w.WriteStartAttribute (GetNSResolver (iter).LookupPrefix (name.Namespace), name.Name, name.Namespace);
+ SerializeContent (iter);
+ w.WriteEndAttribute ();
+ }
+
+ public override XPathSequence Evaluate (XPathSequence iter)
+ {
+ return EvaluateNode (iter, XPathNodeType.Attribute);
+ }
+
+ private XmlQualifiedName EvaluateName (XPathSequence iter)
+ {
+ XmlQualifiedName name = Name;
+ if (NameExpr != null) {
+ XPathAtomicValue value = Atomize (new ExprSequenceIterator (iter, NameExpr));
+ IXmlNamespaceResolver res = GetNSResolver (iter);
+
+ switch (value.XmlType.TypeCode) {
+ case XmlTypeCode.QName:
+ name = (XmlQualifiedName) value.ValueAs (typeof (XmlQualifiedName), res);
+ break;
+ case XmlTypeCode.String:
+ try {
+ // nonprefixed attribute name == element's local namespace
+ if (value.Value.IndexOf (':') < 0)
+ name = new XmlQualifiedName (value.Value);
+ else
+ name = InternalPool.ParseQName (value.Value, res);
+ } catch (ArgumentException ex) {
+ // FIXME: add more info
+ throw new XmlQueryException (String.Format ("The evaluation result of the name expression could not be resolved as a valid QName. Evaluation result string is '{0}'.", value.Value));
+ }
+ break;
+ default:
+ // FIXME: add more info
+ throw new XmlQueryException ("A name of an attribute constructor must be resolved to either a QName or string.");
+ }
+ }
+ return name;
+ }
+#endregion
+ }
+
+ internal class XmlNSConstructor : XmlConstructorExpr
+ {
+ public XmlNSConstructor (string prefix, ExprSequence content)
+ : base (content)
+ {
+ }
+
+ internal override void CheckReference (XQueryASTCompiler compiler)
+ {
+ Content.CheckReference (compiler);
+ }
+
+#region CompileAndEvaluate
+ internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
+ {
+ if (Content != null)
+ for (int i = 0; i < Content.Count; i++)
+ Content [i] = Content [i].Compile (compiler);
+ return this;
+ }
+
+ // FIXME: can be optimized by checking all items in Expr
+ public override SequenceType StaticType {
+ get { return SequenceType.Namespace; }
+ }
+
+ public override void Serialize (XPathSequence iter)
+ {
+ // TBD
+ throw new NotImplementedException ();
+ }
+
+ public override XPathSequence Evaluate (XPathSequence iter)
+ {
+ // TBD
+ throw new NotImplementedException ();
+ }
+#endregion
+ }
+
+ internal class XmlDocConstructor : XmlConstructorExpr
+ {
+ public XmlDocConstructor (ExprSequence content)
+ : base (content)
+ {
+ }
+
+ internal override void CheckReference (XQueryASTCompiler compiler)
+ {
+ if (Content != null)
+ Content.CheckReference (compiler);
+ }
+
+#region CompileAndEvaluate
+ internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
+ {
+ if (Content != null)
+ for (int i = 0; i < Content.Count; i++)
+ Content [i] = Content [i].Compile (compiler);
+ return this;
+ }
+
+ // FIXME: can be optimized by checking all items in Expr
+ public override SequenceType StaticType {
+ get { return SequenceType.Document; }
+ }
+
+ public override void Serialize (XPathSequence iter)
+ {
+ XmlWriter w = iter.Context.Writer;
+ w.WriteStartDocument ();
+ SerializeContent (iter);
+ w.WriteEndDocument ();
+ }
+
+ public override XPathSequence Evaluate (XPathSequence iter)
+ {
+ return EvaluateNode (iter, XPathNodeType.Root);
+ }
+#endregion
+ }
+
+ internal class XmlTextConstructor : XmlConstructorExpr
+ {
+ public XmlTextConstructor (string text)
+ : base (null)
+ {
+ this.text = text;
+ }
+
+ public XmlTextConstructor (ExprSequence content)
+ : base (content)
+ {
+ }
+
+ string text;
+
+ public string LiteralText {
+ get { return text; }
+ }
+
+ internal override void CheckReference (XQueryASTCompiler compiler)
+ {
+ if (Content != null)
+ Content.CheckReference (compiler);
+ }
+
+#region CompileAndEvaluate
+ internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
+ {
+ if (Content != null)
+ for (int i = 0; i < Content.Count; i++)
+ Content [i] = Content [i].Compile (compiler);
+ return this;
+ }
+
+ public override SequenceType StaticType {
+ get { return SequenceType.Text; }
+ }
+
+ public override void Serialize (XPathSequence iter)
+ {
+ if (Content != null)
+ iter.Context.Writer.WriteString (Atomize (new ExprSequenceIterator (iter, Content)).Value);
+ else
+ iter.Context.Writer.WriteString (LiteralText);
+ }
+
+ public override XPathSequence Evaluate (XPathSequence iter)
+ {
+ return EvaluateNode (iter);
+ }
+#endregion
+ }
+
+ internal class XmlCommentConstructor : XmlConstructorExpr
+ {
+ string contentLiteral;
+
+ public XmlCommentConstructor (string content)
+ : base (null)
+ {
+ this.contentLiteral = content;
+ }
+
+ public XmlCommentConstructor (ExprSequence content)
+ : base (content)
+ {
+ }
+
+ internal override void CheckReference (XQueryASTCompiler compiler)
+ {
+ if (Content != null)
+ Content.CheckReference (compiler);
+ }
+
+#region CompileAndEvaluate
+ internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
+ {
+ if (Content != null)
+ for (int i = 0; i < Content.Count; i++)
+ Content [i] = Content [i].Compile (compiler);
+ return this;
+ }
+
+ // FIXME: can be optimized by checking all items in Expr
+ public override SequenceType StaticType {
+ get { return SequenceType.Comment; }
+ }
+
+ public override void Serialize (XPathSequence iter)
+ {
+ iter.Context.Writer.WriteComment (Atomize (new ExprSequenceIterator (iter, Content)).Value);
+ }
+
+ public override XPathSequence Evaluate (XPathSequence iter)
+ {
+ return EvaluateNode (iter);
+ }
+#endregion
+ }
+
+ internal class XmlPIConstructor : XmlConstructorExpr
+ {
+ string name;
+ ExprSequence nameExpr;
+
+ string contentLiteral;
+
+ public XmlPIConstructor (string name, string content)
+ : base (null)
+ {
+ this.name = name;
+ this.contentLiteral = content;
+ }
+
+ public XmlPIConstructor (string name, ExprSequence content)
+ : base (content)
+ {
+ this.name = name;
+ }
+
+ public XmlPIConstructor (ExprSequence name, ExprSequence content)
+ : base (content)
+ {
+ this.nameExpr = name;
+ }
+
+ internal override void CheckReference (XQueryASTCompiler compiler)
+ {
+ if (nameExpr != null)
+ nameExpr.CheckReference (compiler);
+ if (Content != null)
+ Content.CheckReference (compiler);
+ }
+
+#region CompileAndEvaluate
+ internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
+ {
+ if (NameExpr != null)
+ for (int i = 0; i < NameExpr.Count; i++)
+ NameExpr [i] = NameExpr [i].Compile (compiler);
+ if (Content != null)
+ for (int i = 0; i < Content.Count; i++)
+ Content [i] = Content [i].Compile (compiler);
+ return this;
+ }
+
+ public string Name {
+ get { return name; }
+ }
+
+ public ExprSequence NameExpr {
+ get { return nameExpr; }
+ }
+
+ // FIXME: can be optimized by checking all items in Expr
+ public override SequenceType StaticType {
+ get { return SequenceType.XmlPI; }
+ }
+
+ public override void Serialize (XPathSequence iter)
+ {
+ iter.Context.Writer.WriteProcessingInstruction (
+ GetName (iter),
+ Atomize (new ExprSequenceIterator (iter, Content)).Value);
+ }
+
+ public override XPathSequence Evaluate (XPathSequence iter)
+ {
+ return EvaluateNode (iter);
+ }
+
+ private string GetName (XPathSequence iter)
+ {
+ if (Name != String.Empty)
+ return Name;
+ return Atomize (new ExprSequenceIterator (iter, NameExpr)).Value;
+ }
+#endregion
+ }
+}
+
+#endif
diff --git a/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XQueryFunction.cs b/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XQueryFunction.cs
new file mode 100755
index 00000000000..d0a745e8f7b
--- /dev/null
+++ b/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XQueryFunction.cs
@@ -0,0 +1,322 @@
+//
+// XQueryFunction.cs - XQuery 1.0 and XPath 2.0 Functions implementation
+//
+// Author:
+// Atsushi Enomoto <atsushi@ximian.com>
+//
+//
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+//
+// See XQuery 1.0 and XPath 2.0 Functions and Operators.
+//
+#if NET_2_0
+using System;
+using System.Collections;
+using System.Reflection;
+using System.Xml;
+using System.Xml.Schema;
+using System.Xml.Query;
+using System.Xml.XPath;
+using System.Xml.Xsl;
+using Mono.Xml;
+
+namespace Mono.Xml.XPath2
+{
+ // It is instantiated per function definition. (e.g. fn:string(), fn:data(), fn:contat()).
+ public abstract class XQueryFunction
+ {
+ public const string Namespace = "http://www.w3.org/2004/07/xpath-functions";
+
+ static XQueryFunctionTable defaultFunctions = new XQueryFunctionTable ();
+
+ static XQueryFunction ()
+ {
+ defaultFunctions.Add (FromName ("node-name", "FnNodeName"));
+ defaultFunctions.Add (FromName ("nilled", "FnNilled"));
+ defaultFunctions.Add (FromName ("string", "FnString"));
+ defaultFunctions.Add (FromName ("data", "FnData"));
+ defaultFunctions.Add (FromName ("base-uri", "FnBaseUri"));
+ defaultFunctions.Add (FromName ("document-uri", "FnDocumentUri"));
+ defaultFunctions.Add (FromName ("error", "FnError"));
+ defaultFunctions.Add (FromName ("trace", "FnTrace"));
+ defaultFunctions.Add (FromName ("abs", "FnAbs"));
+ defaultFunctions.Add (FromName ("ceiling", "FnCeiling"));
+ defaultFunctions.Add (FromName ("floor", "FnFloor"));
+ defaultFunctions.Add (FromName ("round", "FnRound"));
+ defaultFunctions.Add (FromName ("round-half-to-even", "FnRoundHalfToEven"));
+ defaultFunctions.Add (FromName ("codepoints-to-string", "FnCodepointsToString"));
+ defaultFunctions.Add (FromName ("string-to-codepoints", "FnStringToCodepoints"));
+ defaultFunctions.Add (FromName ("compare", "FnCompare"));
+ defaultFunctions.Add (FromName ("concat", "FnConcat"));
+ defaultFunctions.Add (FromName ("string-join", "FnStringJoin"));
+ defaultFunctions.Add (FromName ("substring", "FnSubstring"));
+ defaultFunctions.Add (FromName ("string-length", "FnStringLength"));
+ defaultFunctions.Add (FromName ("normaize-space", "FnNormalizeSpace"));
+ defaultFunctions.Add (FromName ("normalize-unicode", "FnNormalizeUnicode"));
+ defaultFunctions.Add (FromName ("uppercase", "FnUpperCase"));
+ defaultFunctions.Add (FromName ("lowercase", "FnLowerCase"));
+ defaultFunctions.Add (FromName ("translate", "FnTranslate"));
+ defaultFunctions.Add (FromName ("escape-uri", "FnEscapeUri"));
+ defaultFunctions.Add (FromName ("contains", "FnContains"));
+ defaultFunctions.Add (FromName ("starts-with", "FnStartsWith"));
+ defaultFunctions.Add (FromName ("ends-with", "FnEndsWith"));
+ defaultFunctions.Add (FromName ("substring-before", "FnSubstringBefore"));
+ defaultFunctions.Add (FromName ("substring-after", "FnSubstringAfter"));
+ defaultFunctions.Add (FromName ("matches", "FnMatches"));
+ defaultFunctions.Add (FromName ("replace", "FnReplace"));
+ defaultFunctions.Add (FromName ("tokenize", "FnTokenize"));
+ defaultFunctions.Add (FromName ("resolve-uri", "FnResolveUri"));
+ defaultFunctions.Add (FromName ("true", "FnTrue"));
+ defaultFunctions.Add (FromName ("false", "FnFalse"));
+ defaultFunctions.Add (FromName ("not", "FnNot"));
+
+ defaultFunctions.Add (FromName ("resolve-qname", "FnResolveQName"));
+ defaultFunctions.Add (FromName ("expand-qname", "FnExpandQName"));
+ defaultFunctions.Add (FromName ("namespace-uri-for-prefix", "FnNamespaceUriForPrefix"));
+ defaultFunctions.Add (FromName ("in-scope-prefixes", "FnInScopePrefixes"));
+ defaultFunctions.Add (FromName ("name", "FnName"));
+ defaultFunctions.Add (FromName ("local-name", "FnLocalName"));
+ defaultFunctions.Add (FromName ("namespace-uri", "FnNamespaceUri"));
+ defaultFunctions.Add (FromName ("number", "FnNumber"));
+ defaultFunctions.Add (FromName ("lang", "FnLang"));
+ defaultFunctions.Add (FromName ("root", "FnRoot"));
+ defaultFunctions.Add (FromName ("boolean", "FnBoolean"));
+ defaultFunctions.Add (FromName ("indexof", "FnIndexOf"));
+ defaultFunctions.Add (FromName ("empty", "FnEmpty"));
+ defaultFunctions.Add (FromName ("exists", "FnExists"));
+ defaultFunctions.Add (FromName ("distinct-values", "FnDistinctValues"));
+ defaultFunctions.Add (FromName ("insert-before", "FnInsertBefore"));
+ defaultFunctions.Add (FromName ("remove", "FnRemove"));
+ defaultFunctions.Add (FromName ("reverse", "FnReverse"));
+ defaultFunctions.Add (FromName ("subsequence", "FnSubsequence"));
+ defaultFunctions.Add (FromName ("unordered", "FnUnordered"));
+ defaultFunctions.Add (FromName ("zero-or-one", "FnZeroOrOne"));
+ defaultFunctions.Add (FromName ("one-or-more", "FnOneOrMore"));
+ defaultFunctions.Add (FromName ("exactly-one", "FnExactlyOne"));
+ defaultFunctions.Add (FromName ("deep-equal", "FnDeepEqual"));
+ defaultFunctions.Add (FromName ("count", "FnCount"));
+ defaultFunctions.Add (FromName ("avg", "FnAvg"));
+ defaultFunctions.Add (FromName ("max", "FnMax"));
+ defaultFunctions.Add (FromName ("min", "FnMin"));
+ defaultFunctions.Add (FromName ("sum", "FnSum"));
+ defaultFunctions.Add (FromName ("id", "FnId"));
+ defaultFunctions.Add (FromName ("idref", "FnIdRef"));
+ defaultFunctions.Add (FromName ("doc", "FnDoc"));
+ defaultFunctions.Add (FromName ("collection", "FnCollection"));
+ defaultFunctions.Add (FromName ("position", "FnPosition"));
+ defaultFunctions.Add (FromName ("last", "FnLast"));
+ defaultFunctions.Add (FromName ("current-datetime", "FnCurrentDateTime"));
+ defaultFunctions.Add (FromName ("current-date", "FnCurrentDate"));
+ defaultFunctions.Add (FromName ("current-time", "FnCurrentTime"));
+ defaultFunctions.Add (FromName ("default-collation", "FnDefaultCollation"));
+ defaultFunctions.Add (FromName ("implicit-timezone", "FnImplicitTimeZone"));
+// defaultFunctions.Add (FromName ("years-from-duration", "FnYearsFromDuration"));
+/*
+ fnAtomicConstructor,
+ fnYearsFromDuration, fnMonthsFromDuration,
+ fnDaysFromDuration, fnHoursFromDuration,
+ fnMinutesFromDuration, fnSecondsFromDuration,
+ fnYearFromDateTime, fnMonthFromDateTime,
+ fnDayFromDateTime, fnHoursFromDateTime,
+ fnMinutesFromDateTime, fnSecondsFromDateTime,
+ fnTimeZoneFromDateTime, fnYearFromDate, fnMonthFromDate,
+ fnDayFromDate, fnTimeZoneFromDate, fnHoursFromTime,
+ fnMinutesFromTime, fnSecondsFromTime,
+ fnTimeZoneFromTime, fnAdjustDateTimeToTimeZone,
+ fnAdjustDateToTimeZone, fnAdjustTimeToTimeZone,
+ fnSubtractDateTimesYieldingYearMonthDuration,
+ fnSubtractDateTimesYieldingDayTimeDuration,
+ fnSubtractDatesYieldingYearMonthDuration,
+ fnSubtractDatesYieldingDayTimeDuration,
+ fnSubtractTimes,
+*/
+ }
+
+ private static XQueryCliFunction FromName (string xname, string cliname)
+ {
+ return XQueryCliFunction.CreateFromMethodInfo (
+ new XmlQualifiedName (xname, XQueryFunction.Namespace),
+ FindNamedMethods (typeof (XQueryFunctionCliImpl), cliname)
+ );
+ }
+
+ internal static XQueryCliFunction FromQName (XmlQualifiedName qname)
+ {
+ return XQueryCliFunction.CreateFromMethodInfo (
+ qname, FindNamedMethods (Type.GetType (qname.Namespace), qname.Name));
+ }
+
+ private static bool FilterImpl (MemberInfo m, object filterCriteria)
+ {
+ return m.Name == filterCriteria.ToString ();
+ }
+
+ private static MemberFilter memberFilter = new MemberFilter (FilterImpl);
+
+ private static MethodInfo [] FindNamedMethods (Type type, string name)
+ {
+ ArrayList al = new ArrayList (
+ type.FindMembers (
+ MemberTypes.Method,
+ BindingFlags.Default | BindingFlags.Public | BindingFlags.Static,
+ // FIXME: wait for anonymous method support
+// delegate (MemberInfo m, object filterCriteria) {
+// return m.Name == filterCriteria.ToString ();
+// },
+ memberFilter,
+ name));
+ return al.ToArray (typeof (MethodInfo)) as MethodInfo [];
+ }
+
+ internal static XQueryFunction FindKnownFunction (
+ XmlQualifiedName name)
+ {
+ switch (name.Namespace) {
+ case XQueryFunction.Namespace:
+ return defaultFunctions [name];
+ case InternalPool.XdtNamespace:
+ case XmlSchema.Namespace:
+ XmlSchemaType type = XmlSchemaType.GetBuiltInSimpleType (name);
+ if (type != null)
+ return null; // FIXME: atomic constructor
+ type = XmlSchemaType.GetBuiltInComplexType (name);
+ if (type == null)
+ return null; // FIXME: atomic constructor?
+ return null;
+ default:
+ return null;
+ }
+ }
+
+ // Constructor
+
+ internal XQueryFunction (XmlQualifiedName name, XQueryFunctionArgument [] args, SequenceType returnType)
+ {
+ this.name = name;
+ this.args = args;
+ this.returnType = returnType;
+ }
+
+ // Fields
+
+ XmlQualifiedName name;
+ XQueryFunctionArgument [] args;
+ SequenceType returnType;
+
+ // Properties
+
+ public XmlQualifiedName Name {
+ get { return name; }
+ }
+
+ public abstract int MinArgs { get; }
+ public abstract int MaxArgs { get; }
+
+ public XQueryFunctionArgument [] Args {
+ get { return args; }
+ }
+
+ public SequenceType ReturnType {
+ get { return returnType; }
+ }
+
+ public abstract object Invoke (XPathSequence current, object [] args);
+
+ public virtual XPathSequence Evaluate (XPathSequence iter, ExprSequence args)
+ {
+ object [] instParams = new object [args.Count];
+ for (int i = 0; i < args.Count; i++) {
+ XPathSequence val = args [i].Evaluate (iter);
+ instParams [i] = Args [i].Type.ToRuntimeType (val);
+ }
+ object o = Invoke (iter, instParams);
+ if (o == null)
+ return new XPathEmptySequence (iter.Context);
+ if (o is XPathSequence)
+ return (XPathSequence) o;
+ XPathItem item = o as XPathItem;
+ if (item == null)
+ item = new XPathAtomicValue (o, ReturnType.SchemaType);
+ return new SingleItemIterator (item, iter.Context);
+ }
+ }
+
+ public class XQueryFunctionArgument
+ {
+ public XQueryFunctionArgument (XmlQualifiedName name, SequenceType type)
+ {
+ this.name = name;
+ this.type = type;
+ }
+
+ XmlQualifiedName name;
+ SequenceType type;
+
+ public XmlQualifiedName Name {
+ get { return name; }
+ }
+
+ public SequenceType Type {
+ get { return type; }
+ }
+ }
+
+ public class XQueryUserFunction : XQueryFunction
+ {
+ ExprSequence expr;
+
+ internal XQueryUserFunction (XmlQualifiedName name,
+ XQueryFunctionArgument [] parameters,
+ ExprSequence expr,
+ SequenceType returnType)
+ : base (name, parameters, returnType)
+ {
+ this.expr = expr;
+ }
+
+ public override int MinArgs {
+ get { return Args.Length; }
+ }
+
+ public override int MaxArgs {
+ get { return Args.Length; }
+ }
+
+ public override object Invoke (XPathSequence current, object [] args)
+ {
+ throw new SystemException ("XQuery internal error: should not happen.");
+ }
+
+ public override XPathSequence Evaluate (XPathSequence iter, ExprSequence args)
+ {
+ for (int i = 0; i < Args.Length; i++)
+ iter.Context.PushVariable (Args [i].Name, args [i].Evaluate (iter));
+ XPathSequence seq = new ExprSequenceIterator (iter, expr);
+ for (int i = 0; i < Args.Length; i++)
+ iter.Context.PopVariable ();
+ return seq;
+ }
+ }
+}
+#endif
diff --git a/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XQueryFunctionCliImpl.cs b/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XQueryFunctionCliImpl.cs
new file mode 100755
index 00000000000..690851a3147
--- /dev/null
+++ b/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XQueryFunctionCliImpl.cs
@@ -0,0 +1,1135 @@
+//
+// XQueryFunctionCliImple.cs
+//
+// Author:
+// Atsushi Enomoto <atsushi@ximian.com>
+//
+//
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+//
+// Runtime-level (native) implementation of XQuery 1.0 and XPath 2.0
+// Functions implementation. XQueryCliFunction
+// See XQuery 1.0 and XPath 2.0 Functions and Operators.
+//
+#if NET_2_0
+using System;
+using System.Collections;
+using System.Globalization;
+using System.IO;
+using System.Text.RegularExpressions;
+using System.Xml;
+using System.Xml.Query;
+using System.Xml.Schema;
+using System.Xml.XPath;
+using Mono.Xml;
+
+namespace Mono.Xml.XPath2
+{
+ public class XQueryFunctionCliImpl
+ {
+ internal static XmlSchemaType XmlTypeFromCliType (Type cliType)
+ {
+ switch (Type.GetTypeCode (cliType)) {
+ case TypeCode.Int32:
+ return InternalPool.XsInt;
+ case TypeCode.Decimal:
+ return InternalPool.XsDecimal;
+ case TypeCode.Double:
+ return InternalPool.XsDouble;
+ case TypeCode.Single:
+ return InternalPool.XsFloat;
+ case TypeCode.Int64:
+ return InternalPool.XsLong;
+ case TypeCode.Int16:
+ return InternalPool.XsShort;
+ case TypeCode.UInt16:
+ return InternalPool.XsUnsignedShort;
+ case TypeCode.UInt32:
+ return InternalPool.XsUnsignedInt;
+ case TypeCode.String:
+ return InternalPool.XsString;
+ case TypeCode.DateTime:
+ return InternalPool.XsDateTime;
+ case TypeCode.Boolean:
+ return InternalPool.XsBoolean;
+ }
+ if (cliType == typeof (XmlQualifiedName))
+ return InternalPool.XsQName;
+ return null;
+ }
+
+ private static XPathItem ToItem (object arg)
+ {
+ if (arg == null)
+ return null;
+ XPathItem item = arg as XPathItem;
+ if (item != null)
+ return item;
+ XPathSequence seq = arg as XPathSequence;
+ if (seq != null)
+ return seq.MoveNext () ? seq.Current : null;
+ return new XPathAtomicValue (arg, XmlTypeFromCliType (arg.GetType ()));
+ }
+
+ // Accessors
+
+ public static XmlQualifiedName FnNodeName (XPathNavigator arg)
+ {
+ if (arg == null)
+ return null;
+
+ return arg.LocalName == String.Empty ?
+ XmlQualifiedName.Empty :
+ new XmlQualifiedName (arg.LocalName, arg.NamespaceURI);
+ }
+
+ public static bool FnNilled (XPathNavigator arg)
+ {
+ if (arg == null)
+ throw new XmlQueryException ("Function nilled() does not allow empty sequence parameter.");
+
+ IXmlSchemaInfo info = arg.NodeType == XPathNodeType.Element ? arg.SchemaInfo : null;
+ return info != null && info.IsNil;
+ }
+
+ public static string FnString (XQueryContext context)
+ {
+ XPathItem item = context.CurrentItem;
+ if (item == null)
+ throw new ArgumentException ("FONC0001: undefined context item");
+ return FnString (item);
+ }
+
+ [MonoTODO]
+ public static string FnString (object arg)
+ {
+ if (arg == null)
+ return String.Empty;
+ XPathNavigator nav = arg as XPathNavigator;
+ if (nav != null)
+ return nav.Value;
+ // FIXME: it should be exactly the same as "arg cast as xs:string"
+ XPathItem item = ToItem (arg);
+ return item != null ? XQueryConvert.ItemToString (item) : null;
+ }
+
+ [MonoTODO]
+ public static XPathAtomicValue FnData (object arg)
+ {
+ // FIXME: parameter should be object []
+ XPathNavigator nav = arg as XPathNavigator;
+ if (nav != null) {
+ XmlSchemaType st = nav.SchemaInfo != null ? nav.SchemaInfo.SchemaType : null;
+ return new XPathAtomicValue (nav.TypedValue, st != null ? st : InternalPool.XsAnyType);
+ }
+ else
+ return (XPathAtomicValue) arg;
+ }
+
+ public static string FnBaseUri (XPathNavigator nav)
+ {
+ return nav != null ? nav.BaseURI : null;
+ }
+
+ public static string FnDocumentUri (XPathNavigator nav)
+ {
+ if (nav == null)
+ return null;
+ XPathNavigator root = nav.Clone ();
+ root.MoveToRoot ();
+ return root.BaseURI;
+ }
+
+ // Error
+
+ [MonoTODO]
+ public static void FnError (object arg)
+ {
+ throw new NotImplementedException ();
+ }
+
+ // Trace
+
+ [MonoTODO]
+ public static object FnTrace (XQueryContext ctx, object value, string label)
+ {
+ if (value == null)
+ return new XPathEmptySequence (ctx);
+ XPathSequence seq = value as XPathSequence;
+ if (seq == null) {
+ XPathAtomicValue av = value as XPathAtomicValue;
+ if (av == null)
+ av = new XPathAtomicValue (value,
+ InternalPool.GetBuiltInType (
+ InternalPool.XmlTypeCodeFromRuntimeType (
+ value.GetType (), true)));
+ seq = new SingleItemIterator (av, ctx);
+ }
+ return new TracingIterator (seq, label);
+ }
+
+ // Numeric Operation
+
+ [MonoTODO]
+ public static object FnAbs (object arg)
+ {
+ if (arg is int)
+ return System.Math.Abs ((int) arg);
+ if (arg is long)
+ return System.Math.Abs ((long) arg);
+ else if (arg is decimal)
+ return System.Math.Abs ((decimal) arg);
+ else if (arg is double)
+ return System.Math.Abs ((double) arg);
+ else if (arg is float)
+ return System.Math.Abs ((float) arg);
+ else if (arg is short)
+ return System.Math.Abs ((short) arg);
+ else if (arg is uint || arg is ulong || arg is ushort)
+ return arg;
+ return null;
+ }
+
+ [MonoTODO]
+ public static object FnCeiling (object arg)
+ {
+ if (arg is decimal) {
+ decimal d = (decimal) arg;
+ decimal d2 = Decimal.Floor (d);
+ return d2 != d ? d2 + 1 : d2;
+ }
+ else if (arg is double || arg is float)
+ return System.Math.Ceiling ((double) arg);
+ else if (arg is int || arg is long || arg is short || arg is uint || arg is ulong || arg is ushort)
+ return arg;
+ return null;
+ }
+
+ [MonoTODO]
+ public static object FnFloor (object arg)
+ {
+ if (arg is decimal)
+ return Decimal.Floor ((decimal) arg);
+ else if (arg is double || arg is float)
+ return System.Math.Floor ((double) arg);
+ else if (arg is int || arg is long || arg is short || arg is uint || arg is ulong || arg is ushort)
+ return arg;
+ return null;
+ }
+
+ [MonoTODO]
+ public static object FnRound (object arg)
+ {
+ if (arg is decimal)
+ return Decimal.Round ((decimal) arg, 0);
+ else if (arg is double || arg is float)
+ return System.Math.Round ((double) arg);
+ else if (arg is int || arg is long || arg is short || arg is uint || arg is ulong || arg is ushort)
+ return arg;
+ return null;
+ }
+
+ [MonoTODO]
+ public static object FnRoundHalfToEven (object arg)
+ {
+ throw new NotImplementedException ();
+ }
+
+ [MonoTODO]
+ public static string FnCodepointsToString (int [] arg)
+ {
+ throw new NotImplementedException ();
+ }
+
+ [MonoTODO]
+ public static int [] FnStringToCodepoints (string arg)
+ {
+ throw new NotImplementedException ();
+ }
+
+ public static int FnCompare (XQueryContext ctx, string s1, string s2)
+ {
+ return FnCompare (s1, s2, ctx.DefaultCollation);
+ }
+
+ public static int FnCompare (XQueryContext ctx, string s1, string s2, string collation)
+ {
+ return FnCompare (s1, s2, ctx.GetCulture (collation));
+ }
+
+ private static int FnCompare (string s1, string s2, CultureInfo ci)
+ {
+ return ci.CompareInfo.Compare (s1, s2);
+ }
+
+ public static string FnConcat (object o1, object o2)
+ {
+ return String.Concat (o1, o2);
+ }
+
+ public static string FnStringJoin (string [] strings, string separator)
+ {
+ return String.Join (separator, strings);
+ }
+
+ public static string FnSubstring (string src, double loc)
+ {
+ return src.Substring ((int) loc);
+ }
+
+ public static string FnSubstring (string src, double loc, double length)
+ {
+ return src.Substring ((int) loc, (int) length);
+ }
+
+ public static int FnStringLength (XQueryContext ctx)
+ {
+ return FnString (ctx).Length;
+ }
+
+ public static int FnStringLength (string s)
+ {
+ return s.Length;
+ }
+
+ public static string FnNormalizeSpace (XQueryContext ctx)
+ {
+ return FnNormalizeSpace (FnString (ctx));
+ }
+
+ [MonoTODO]
+ public static string FnNormalizeSpace (string s)
+ {
+ throw new NotImplementedException ();
+ }
+
+ public static string FnNormalizeUnicode (string arg)
+ {
+ return FnNormalizeUnicode (arg, "NFC");
+ }
+
+ [MonoTODO]
+ public static string FnNormalizeUnicode (string arg, string normalizationForm)
+ {
+ throw new NotImplementedException ();
+ }
+
+ public static string FnUpperCase (string arg)
+ {
+ // FIXME: supply culture
+ return arg.ToUpper ();
+ }
+
+ public static string FnLowerCase (string arg)
+ {
+ // FIXME: supply culture
+ return arg.ToLower ();
+ }
+
+ public static string FnTranslate (string arg, string mapString, string transString)
+ {
+ return arg == null ? null : arg.Replace (mapString, transString);
+ }
+
+ [MonoTODO]
+ public static string FnEscapeUri (string uriPart, bool escapeReserved)
+ {
+ throw new NotImplementedException ();
+ }
+
+ public static bool FnContains (XQueryContext ctx, string arg1, string arg2)
+ {
+ return FnContains (arg1, arg2, ctx.DefaultCollation);
+ }
+
+ public static bool FnContains (XQueryContext ctx, string arg1, string arg2, string collation)
+ {
+ return FnContains (arg1, arg2, ctx.GetCulture (collation));
+ }
+
+ private static bool FnContains (string arg1, string arg2, CultureInfo ci)
+ {
+ if (arg1 == null)
+ arg1 = String.Empty;
+ if (arg2 == null)
+ arg2 = String.Empty;
+ if (arg2 == String.Empty)
+ return true;
+ return ci.CompareInfo.IndexOf (arg1, arg2) >= 0;
+ }
+
+ public static bool FnStartsWith (XQueryContext ctx, string arg1, string arg2)
+ {
+ return FnStartsWith (arg1, arg2, ctx.DefaultCollation);
+ }
+
+ public static bool FnStartsWith (XQueryContext ctx, string arg1, string arg2, string collation)
+ {
+ return FnStartsWith (arg1, arg2, ctx.GetCulture (collation));
+ }
+
+ private static bool FnStartsWith (string arg1, string arg2, CultureInfo ci)
+ {
+ return ci.CompareInfo.IsPrefix (arg1, arg2);
+ }
+
+ public static bool FnEndsWith (XQueryContext ctx, string arg1, string arg2)
+ {
+ return FnEndsWith (arg1, arg2, ctx.DefaultCollation);
+ }
+
+ public static bool FnEndsWith (XQueryContext ctx, string arg1, string arg2, string collation)
+ {
+ return FnEndsWith (arg1, arg2, ctx.GetCulture (collation));
+ }
+
+ private static bool FnEndsWith (string arg1, string arg2, CultureInfo ci)
+ {
+ return ci.CompareInfo.IsSuffix (arg1, arg2);
+ }
+
+ public static string FnSubstringBefore (XQueryContext ctx, string arg1, string arg2)
+ {
+ return FnSubstringBefore (arg1, arg2, ctx.DefaultCollation);
+ }
+
+ public static string FnSubstringBefore (XQueryContext ctx, string arg1, string arg2, string collation)
+ {
+ return FnSubstringBefore (arg1, arg2, ctx.GetCulture (collation));
+ }
+
+ private static string FnSubstringBefore (string arg1, string arg2, CultureInfo ci)
+ {
+ int index = ci.CompareInfo.IndexOf (arg1, arg2);
+ return arg1.Substring (0, index);
+ }
+
+ public static string FnSubstringAfter (XQueryContext ctx, string arg1, string arg2)
+ {
+ return FnSubstringAfter (arg1, arg2, ctx.DefaultCollation);
+ }
+
+ public static string FnSubstringAfter (XQueryContext ctx, string arg1, string arg2, string collation)
+ {
+ return FnSubstringAfter (arg1, arg2, ctx.GetCulture (collation));
+ }
+
+ private static string FnSubstringAfter (string arg1, string arg2, CultureInfo ci)
+ {
+ int index = ci.CompareInfo.IndexOf (arg1, arg2);
+ return arg1.Substring (index);
+ }
+
+ public static bool FnMatches (string input, string pattern)
+ {
+ return new Regex (pattern).IsMatch (input);
+ }
+
+ [MonoTODO]
+ public static bool FnMatches (string input, string pattern, string flags)
+ {
+ throw new NotImplementedException ();
+ }
+
+ public static string FnReplace (string input, string pattern, string replace)
+ {
+ return new Regex (pattern).Replace (input, replace);
+ }
+
+ [MonoTODO]
+ public static string FnReplace (string input, string pattern, string replace, string flags)
+ {
+ throw new NotImplementedException ();
+ }
+
+ public static string [] FnTokenize (string input, string pattern)
+ {
+ return new Regex (pattern).Split (input);
+ }
+
+ [MonoTODO]
+ public static string [] FnTokenize (string input, string pattern, string flags)
+ {
+ throw new NotImplementedException ();
+ }
+
+ public static string FnResolveUri (XQueryContext ctx, string relUri)
+ {
+ return new Uri (new Uri (ctx.StaticContext.BaseUri), relUri).ToString ();
+ }
+
+ public static string FnResolveUri (string relUri, string baseUri)
+ {
+ return new Uri (new Uri (baseUri), relUri).ToString ();
+ }
+
+ public static object FnTrue ()
+ {
+ return true;
+ }
+
+ public static object FnFalse ()
+ {
+ return false;
+ }
+
+ public static object FnNot (bool value)
+ {
+ return !value;
+ }
+
+ // FIXME: add a bunch of annoying datetime functions
+
+ public static object FnResolveQName (string qname, XPathNavigator element)
+ {
+ if (qname == null)
+ return null;
+
+ int index = qname.IndexOf (':');
+ string prefix = (index < 0) ? "" : qname.Substring (index);
+ return new XmlQualifiedName (
+ element.LookupNamespace (prefix),
+ index < 0 ? qname : qname.Substring (index + 1));
+ }
+
+ public static object FnExpandQName (string ns, string local)
+ {
+ return new XmlQualifiedName (local, ns);
+ }
+
+ public static string FnLocalNameFromQName (XmlQualifiedName name)
+ {
+ return name != null ? name.Name : null;
+ }
+
+ public static object FnNamespaceUriFromQName (XmlQualifiedName name)
+ {
+ return name != null ? name.Namespace : null;
+ }
+
+ public static object FnNamespaceUriForPrefix (XQueryContext context, string prefix)
+ {
+ return prefix != null ? context.LookupNamespace (prefix) : null;
+ }
+
+ public static string [] FnInScopePrefixes (XQueryContext context)
+ {
+ IDictionary dict = context.GetNamespacesInScope (XmlNamespaceScope.ExcludeXml);
+ ArrayList keys = new ArrayList (dict.Keys);
+ return keys.ToArray (typeof (string)) as string [];
+ }
+
+ public static string FnName (XPathNavigator nav)
+ {
+ return nav != null ? nav.Name : null;
+ }
+
+ public static string FnLocalName (XPathNavigator nav)
+ {
+ return nav != null ? nav.LocalName : null;
+ }
+
+ public static string FnNamespaceUri (XPathNavigator nav)
+ {
+ return nav != null ? nav.NamespaceURI : null;
+ }
+
+ public static double FnNumber (XQueryContext ctx)
+ {
+ return FnNumber (ctx.CurrentItem);
+ }
+
+ public static double FnNumber (object arg)
+ {
+ if (arg == null)
+ throw new XmlQueryException ("Context item could not be ndetermined during number() evaluation.");
+ XPathItem item = ToItem (arg);
+ return XQueryConvert.ItemToDouble (item);
+ }
+
+ public static bool FnLang (XQueryContext ctx, string testLang)
+ {
+ return FnLang (testLang, ctx.CurrentNode);
+ }
+
+ public static bool FnLang (string testLang, XPathNavigator node)
+ {
+ return testLang == node.XmlLang;
+ }
+
+ public static XPathNavigator FnRoot (XQueryContext ctx)
+ {
+ if (ctx.CurrentItem == null)
+ throw new XmlQueryException ("FONC0001: Undefined context item.");
+ if (ctx.CurrentNode == null)
+ throw new XmlQueryException ("FOTY0011: Context item is not a node.");
+ return FnRoot (ctx.CurrentNode);
+ }
+
+ public static XPathNavigator FnRoot (XPathNavigator node)
+ {
+ if (node == null)
+ return null;
+ XPathNavigator root = node.Clone ();
+ root.MoveToRoot ();
+ return root;
+ }
+
+ public static bool FnBoolean (IEnumerator e)
+ {
+ if (!e.MoveNext ())
+ return false;
+ XPathItem item = e.Current as XPathItem;
+ if (e.MoveNext ())
+ return true;
+ return XQueryConvert.ItemToBoolean (item);
+ }
+
+ public static XPathSequence FnIndexOf (XQueryContext ctx, XPathSequence items, XPathItem item)
+ {
+ return FnIndexOf (ctx, items, item, ctx.DefaultCollation);
+ }
+
+ public static XPathSequence FnIndexOf (XQueryContext ctx, XPathSequence items, XPathItem item, CultureInfo ci)
+ {
+ ArrayList al = new ArrayList ();
+ IEnumerator e = items.GetEnumerator ();
+ for (int i = 0; e.MoveNext (); i++) {
+ XPathItem iter = e.Current as XPathItem;
+ if (iter.XmlType.TypeCode == XmlTypeCode.String) {
+ if (ci.CompareInfo.Compare (iter.Value, item.Value) == 0)
+ al.Add (i);
+ }
+ else {
+ IComparable ic = (IComparable) iter.TypedValue;
+ if (ic.CompareTo ((IComparable) item.TypedValue) == 0)
+ al.Add (i);
+ }
+ }
+ return new ListIterator (ctx, al);
+ }
+
+ public static bool FnEmpty (XPathSequence e)
+ {
+ if (e is XPathEmptySequence)
+ return true;
+ return !e.GetEnumerator ().MoveNext ();
+ }
+
+ public static bool FnExists (XPathSequence e)
+ {
+ if (e is XPathEmptySequence)
+ return false;
+ return e.MoveNext ();
+ }
+
+ public static XPathSequence FnDistinctValues (XQueryContext ctx, XPathSequence items)
+ {
+ return FnDistinctValuesImpl (ctx, items, ctx.DefaultCollation);
+ }
+
+ public static XPathSequence FnDistinctValues (XQueryContext ctx, XPathSequence items, string collation)
+ {
+ return FnDistinctValuesImpl (ctx, items, ctx.GetCulture (collation));
+ }
+
+ private static XPathSequence FnDistinctValuesImpl (XQueryContext ctx, XPathSequence items, CultureInfo collation)
+ {
+ return new DistinctValueIterator (ctx, items, collation);
+ }
+
+ public static XPathSequence FnInsertBefore (XPathSequence target, int position, XPathSequence inserts)
+ {
+ if (position < 1)
+ position = 1;
+ return new InsertingIterator (target, position, inserts);
+ }
+
+ public static XPathSequence FnRemove (XPathSequence target, int position)
+ {
+ if (position < 1)
+ return target;
+ return new RemovalIterator (target, position);
+ }
+
+ [MonoTODO ("optimize")]
+ public static XPathSequence FnReverse (XPathSequence arg)
+ {
+ ArrayList al = new ArrayList ();
+ while (arg.MoveNext ())
+ al.Add (arg.Current);
+ al.Reverse ();
+ return new ListIterator (arg.Context, al);
+ }
+
+ public static object FnSubsequence (XPathSequence sourceSeq, double startingLoc)
+ {
+ return FnSubsequence (sourceSeq, startingLoc, double.MaxValue);
+ }
+
+ [MonoTODO]
+ public static object FnSubsequence (XPathSequence sourceSeq, double startingLoc, double length)
+ {
+ throw new NotImplementedException ();
+ }
+
+ [MonoTODO]
+ // Basically it should be optimized by XQueryASTCompiler
+ public static XPathSequence FnUnordered (XPathSequence e)
+ {
+ return e;
+ }
+
+ public static XPathItem FnZeroOrOne (XPathSequence e)
+ {
+ if (!e.MoveNext ())
+ return null;
+ XPathItem item = e.Current;
+ if (e.MoveNext ())
+ throw new XmlQueryException ("zero-or-one() function detected that the argument sequence contains two or more items.");
+ return item;
+ }
+
+ public static object FnOneOrMore (XPathSequence e)
+ {
+ if (!e.Clone ().MoveNext ())
+ throw new XmlQueryException ("one-or-more() function detected that the argument sequence contains no items.");
+ return e;
+ }
+
+ public static XPathItem FnExactlyOne (XPathSequence e)
+ {
+ if (!e.MoveNext ())
+ throw new XmlQueryException ("exactly-one() function detected that the argument sequence contains no items.");
+ XPathItem item = e.Current;
+ if (e.MoveNext ())
+ throw new XmlQueryException ("exactly-one() function detected that the argument sequence contains two or more items.");
+ return item;
+ }
+
+ public static object FnDeepEqual (XQueryContext ctx, XPathSequence p1, XPathSequence p2)
+ {
+ return FnDeepEqualImpl (p1, p2, ctx.DefaultCollation);
+ }
+
+ public static object FnDeepEqual (XQueryContext ctx, XPathSequence p1, XPathSequence p2, string collation)
+ {
+ return FnDeepEqualImpl (p1, p2, ctx.GetCulture (collation));
+ }
+
+ public static bool FnDeepEqualImpl (XPathSequence p1, XPathSequence p2, CultureInfo collation)
+ {
+ // FIXME: use collation
+ while (p1.MoveNext ()) {
+ if (!p2.MoveNext ())
+ return false;
+ if (!FnDeepEqualItem (p1.Current, p2.Current, collation))
+ return false;
+ }
+ if (p2.MoveNext ())
+ return false;
+ return true;
+ }
+
+ // FIXME: Actually ValueEQ() should consider collation.
+ [MonoTODO]
+ private static bool FnDeepEqualItem (XPathItem i1, XPathItem i2, CultureInfo collation)
+ {
+ XPathAtomicValue av1 = i1 as XPathAtomicValue;
+ XPathAtomicValue av2 = i1 as XPathAtomicValue;
+ if (av1 != null && av2 != null) {
+ try {
+ return XQueryComparisonOperator.ValueEQ (av1, av2);
+ } catch (XmlQueryException) {
+ // not-allowed comparison never raises
+ // an error here, just return false.
+ return false;
+ }
+ }
+ else if (av1 != null || av2 != null)
+ return false;
+
+ XPathNavigator n1 = i1 as XPathNavigator;
+ XPathNavigator n2 = i2 as XPathNavigator;
+ if (n1.NodeType != n2.NodeType)
+ return false;
+ switch (n1.NodeType) {
+ case XPathNodeType.Root:
+ throw new NotImplementedException ();
+ case XPathNodeType.Element:
+ throw new NotImplementedException ();
+ case XPathNodeType.Attribute:
+ return n1.Name == n2.Name && n1.TypedValue == n2.TypedValue;
+ case XPathNodeType.ProcessingInstruction:
+ case XPathNodeType.Namespace:
+ return n1.Name == n2.Name && n1.Value == n2.Value;
+ case XPathNodeType.Text:
+ case XPathNodeType.Comment:
+ return n1.Value == n2.Value;
+ }
+ return false;
+ }
+
+ public static int FnCount (XPathSequence e)
+ {
+ if (e == null)
+ return 0;
+ return e.Count;
+ }
+
+ [MonoTODO]
+ public static object FnAvg (XPathSequence e)
+ {
+ if (!e.MoveNext ())
+ return null;
+ switch (e.Current.XmlType.TypeCode) {
+ case XmlTypeCode.DayTimeDuration:
+ return FnAvgDayTimeDuration (e);
+ case XmlTypeCode.YearMonthDuration:
+ return FnAvgYearMonthDuration (e);
+ case XmlTypeCode.Decimal:
+ return FnAvgDecimal (e);
+ case XmlTypeCode.Integer:
+ return FnAvgInteger (e);
+ case XmlTypeCode.Float:
+ return FnAvgFloat (e);
+ case XmlTypeCode.UntypedAtomic:
+ case XmlTypeCode.Double:
+ return FnAvgDouble (e);
+ }
+ throw new XmlQueryException ("avg() function detected that the sequence contains an item whose type is neither of dayTimeDuration, yearMonthDuration, decimal, integer, float, double, nor untypedAtomic.");
+ }
+
+ private static TimeSpan FnAvgDayTimeDuration (XPathSequence e)
+ {
+ throw new NotImplementedException ();
+ }
+
+ private static TimeSpan FnAvgYearMonthDuration (XPathSequence e)
+ {
+ throw new NotImplementedException ();
+ }
+
+ private static TimeSpan FnAvgDecimal (XPathSequence e)
+ {
+ throw new NotImplementedException ();
+ }
+
+ private static TimeSpan FnAvgInteger (XPathSequence e)
+ {
+ throw new NotImplementedException ();
+ }
+
+ private static TimeSpan FnAvgFloat (XPathSequence e)
+ {
+ throw new NotImplementedException ();
+ }
+
+ private static TimeSpan FnAvgDouble (XPathSequence e)
+ {
+ throw new NotImplementedException ();
+ }
+
+ public static object FnMax (XQueryContext ctx, XPathSequence e)
+ {
+ return FnMaxImpl (e, ctx.DefaultCollation);
+ }
+
+ public static object FnMax (XQueryContext ctx, XPathSequence e, string collation)
+ {
+ return FnMaxImpl (e, ctx.GetCulture (collation));
+ }
+
+ private static object FnMaxImpl (XPathSequence e, CultureInfo collation)
+ {
+ if (!e.MoveNext ())
+ return null;
+ switch (e.Current.XmlType.TypeCode) {
+ case XmlTypeCode.DayTimeDuration:
+ return FnMaxDayTimeDuration (e);
+ case XmlTypeCode.YearMonthDuration:
+ return FnMaxYearMonthDuration (e);
+ case XmlTypeCode.Decimal:
+ return FnMaxDecimal (e);
+ case XmlTypeCode.Integer:
+ return FnMaxInteger (e);
+ case XmlTypeCode.Float:
+ return FnMaxFloat (e);
+ case XmlTypeCode.UntypedAtomic:
+ case XmlTypeCode.Double:
+ return FnMaxDouble (e);
+ }
+ throw new XmlQueryException ("avg() function detected that the sequence contains an item whose type is neither of dayTimeDuration, yearMonthDuration, decimal, integer, float, double, nor untypedAtomic.");
+ }
+
+ private static TimeSpan FnMaxDayTimeDuration (XPathSequence e)
+ {
+ // FIXME: reject yMD (but is it possible...?)
+ TimeSpan ret = TimeSpan.Zero;
+ do {
+ TimeSpan ts = (TimeSpan) e.Current.TypedValue;
+ if (ts > ret)
+ ret = ts;
+ } while (e.MoveNext ());
+ return ret;
+ }
+
+ private static TimeSpan FnMaxYearMonthDuration (XPathSequence e)
+ {
+ // FIXME: reject dTD (but is it possible...?)
+ TimeSpan ret = TimeSpan.Zero;
+ do {
+ TimeSpan ts = (TimeSpan) e.Current.TypedValue;
+ if (ts > ret)
+ ret = ts;
+ } while (e.MoveNext ());
+ return ret;
+ }
+
+ private static decimal FnMaxDecimal (XPathSequence e)
+ {
+ decimal ret = decimal.MinValue;
+ do {
+ ret = System.Math.Max (e.Current.ValueAsDecimal, ret);
+ } while (e.MoveNext ());
+ return ret;
+ }
+
+ private static int FnMaxInteger (XPathSequence e)
+ {
+ int ret = int.MinValue;
+ do {
+ ret = System.Math.Max (e.Current.ValueAsInt32, ret);
+ } while (e.MoveNext ());
+ return ret;
+ }
+
+ private static float FnMaxFloat (XPathSequence e)
+ {
+ float ret = float.MinValue;
+ do {
+ ret = System.Math.Max (e.Current.ValueAsSingle, ret);
+ } while (e.MoveNext ());
+ return ret;
+ }
+
+ private static double FnMaxDouble (XPathSequence e)
+ {
+ double ret = double.MinValue;
+ do {
+ ret = System.Math.Max (e.Current.ValueAsDouble, ret);
+ } while (e.MoveNext ());
+ return ret;
+ }
+
+ public static object FnMin (XQueryContext ctx, XPathSequence e)
+ {
+ return FnMinImpl (e, ctx.DefaultCollation);
+ }
+
+ public static object FnMin (XQueryContext ctx, XPathSequence e, string collation)
+ {
+ return FnMinImpl (e, ctx.GetCulture (collation));
+ }
+
+ private static object FnMinImpl (XPathSequence e, CultureInfo collation)
+ {
+ if (!e.MoveNext ())
+ return null;
+ switch (e.Current.XmlType.TypeCode) {
+ case XmlTypeCode.DayTimeDuration:
+ return FnMinDayTimeDuration (e);
+ case XmlTypeCode.YearMonthDuration:
+ return FnMinYearMonthDuration (e);
+ case XmlTypeCode.Decimal:
+ return FnMinDecimal (e);
+ case XmlTypeCode.Integer:
+ return FnMinInteger (e);
+ case XmlTypeCode.Float:
+ return FnMinFloat (e);
+ case XmlTypeCode.UntypedAtomic:
+ case XmlTypeCode.Double:
+ return FnMinDouble (e);
+ }
+ throw new XmlQueryException ("avg() function detected that the sequence contains an item whose type is neither of dayTimeDuration, yearMonthDuration, decimal, integer, float, double, nor untypedAtomic.");
+ }
+
+ private static TimeSpan FnMinDayTimeDuration (XPathSequence e)
+ {
+ // FIXME: reject yMD (but is it possible...?)
+ TimeSpan ret = TimeSpan.Zero;
+ do {
+ TimeSpan ts = (TimeSpan) e.Current.TypedValue;
+ if (ts > ret)
+ ret = ts;
+ } while (e.MoveNext ());
+ return ret;
+ }
+
+ private static TimeSpan FnMinYearMonthDuration (XPathSequence e)
+ {
+ // FIXME: reject dTD (but is it possible...?)
+ TimeSpan ret = TimeSpan.Zero;
+ do {
+ TimeSpan ts = (TimeSpan) e.Current.TypedValue;
+ if (ts > ret)
+ ret = ts;
+ } while (e.MoveNext ());
+ return ret;
+ }
+
+ private static decimal FnMinDecimal (XPathSequence e)
+ {
+ decimal ret = decimal.MaxValue;
+ do {
+ ret = System.Math.Min (e.Current.ValueAsDecimal, ret);
+ } while (e.MoveNext ());
+ return ret;
+ }
+
+ private static int FnMinInteger (XPathSequence e)
+ {
+ int ret = int.MaxValue;
+ do {
+ ret = System.Math.Min (e.Current.ValueAsInt32, ret);
+ } while (e.MoveNext ());
+ return ret;
+ }
+
+ private static float FnMinFloat (XPathSequence e)
+ {
+ float ret = float.MaxValue;
+ do {
+ ret = System.Math.Min (e.Current.ValueAsSingle, ret);
+ } while (e.MoveNext ());
+ return ret;
+ }
+
+ private static double FnMinDouble (XPathSequence e)
+ {
+ double ret = double.MaxValue;
+ do {
+ ret = System.Math.Min (e.Current.ValueAsDouble, ret);
+ } while (e.MoveNext ());
+ return ret;
+ }
+
+ [MonoTODO]
+ public static object FnSum (XPathSequence e)
+ {
+ throw new NotImplementedException ();
+ }
+
+ [MonoTODO]
+ public static object FnSum (XPathSequence e, XPathItem zero)
+ {
+ throw new NotImplementedException ();
+ }
+
+ public static XPathNavigator FnId (XQueryContext ctx, string id)
+ {
+ return FnId (id, ctx.CurrentNode);
+ }
+
+ public static XPathNavigator FnId (string id, XPathNavigator nav)
+ {
+ XPathNavigator node = nav.Clone ();
+ return node.MoveToId (id) ? node : null;
+ }
+
+ [MonoTODO]
+ public static object FnIdRef (XQueryContext ctx, string arg)
+ {
+ return FnIdRef (arg, ctx.CurrentNode);
+ }
+
+ [MonoTODO]
+ public static object FnIdRef (string arg, XPathNavigator node)
+ {
+ throw new NotImplementedException ();
+ }
+
+ public static XPathNavigator FnDoc (XQueryContext ctx, string uri)
+ {
+ XmlResolver res = ctx.ContextManager.ExtDocResolver;
+ string baseUriString = ctx.StaticContext.BaseUri;
+ Uri baseUri = null;
+ if (baseUriString != null && baseUriString != String.Empty)
+ baseUri = new Uri (baseUriString);
+ Uri relUri = res.ResolveUri (baseUri, uri);
+ Stream s = res.GetEntity (relUri, null, typeof (Stream)) as Stream;
+ try {
+ XPathDocument doc = new XPathDocument (new XmlValidatingReader (new XmlTextReader (s)), XmlSpace.Preserve);
+ return doc.CreateNavigator ();
+ } finally {
+ s.Close ();
+ }
+ }
+
+ public static XPathSequence FnCollection (XQueryContext ctx, string name)
+ {
+ return ctx.ResolveCollection (name);
+ }
+
+ [XQueryFunctionContext]
+ public static int FnPosition (XPathSequence current)
+ {
+ return current.Position;
+ }
+
+ [XQueryFunctionContext]
+ public static int FnLast (XPathSequence current)
+ {
+ return current.Count;
+ }
+
+ public static DateTime FnCurrentDateTime ()
+ {
+ return DateTime.Now;
+ }
+
+ public static DateTime FnCurrentDate ()
+ {
+ return DateTime.Today;
+ }
+
+ public static DateTime FnCurrentTime ()
+ {
+ return new DateTime (DateTime.Now.TimeOfDay.Ticks);
+ }
+
+ [MonoTODO]
+ public static object FnDefaultCollation ()
+ {
+ throw new NotImplementedException ();
+ }
+
+ [MonoTODO]
+ public static object FnImplicitTimeZone ()
+ {
+ throw new NotImplementedException ();
+ }
+ }
+}
+#endif
diff --git a/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XQueryFunctionContextAttribute.cs b/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XQueryFunctionContextAttribute.cs
new file mode 100755
index 00000000000..5c8d6b9c8c4
--- /dev/null
+++ b/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XQueryFunctionContextAttribute.cs
@@ -0,0 +1,45 @@
+//
+// XQueryFunctionContextAttribute.cs
+//
+// Author:
+// Atsushi Enomoto <atsushi@ximian.com>
+//
+//
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// It is used to represent that a function needs current nodeset information.
+//
+#if NET_2_0
+using System;
+using System.Collections;
+using System.Xml;
+using System.Xml.Schema;
+using System.Xml.XPath;
+
+namespace Mono.Xml.XPath2
+{
+ public class XQueryFunctionContextAttribute : Attribute
+ {
+ }
+}
+
+#endif
diff --git a/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XQueryFunctionTable.cs b/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XQueryFunctionTable.cs
new file mode 100755
index 00000000000..7e5254ea324
--- /dev/null
+++ b/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XQueryFunctionTable.cs
@@ -0,0 +1,66 @@
+//
+// XQueryFunctionTable.cs
+//
+// Author:
+// Atsushi Enomoto <atsushi@ximian.com>
+//
+//
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+#if NET_2_0
+using System;
+using System.Collections;
+using System.Reflection;
+using System.Xml;
+using System.Xml.Schema;
+using System.Xml.Query;
+using System.Xml.XPath;
+using System.Xml.Xsl;
+
+namespace Mono.Xml.XPath2
+{
+ public class XQueryFunctionTable : DictionaryBase
+ {
+ public XQueryFunctionTable ()
+ {
+ }
+
+ public XQueryFunction this [XmlQualifiedName name] {
+ get { return Dictionary [name] as XQueryFunction; }
+ }
+
+ internal void Add (XQueryFunction func)
+ {
+ Dictionary.Add (func.Name, func);
+ }
+
+ public ICollection Keys {
+ get { return Dictionary.Keys; }
+ }
+
+ public ICollection Values {
+ get { return Dictionary.Values; }
+ }
+ }
+}
+#endif
diff --git a/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XQueryModuleProlog.cs b/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XQueryModuleProlog.cs
new file mode 100755
index 00000000000..7091c775e71
--- /dev/null
+++ b/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XQueryModuleProlog.cs
@@ -0,0 +1,529 @@
+//
+// XQueryModuleProlog.cs - abstract syntax tree for XQuery
+//
+// Author:
+// Atsushi Enomoto <atsushi@ximian.com>
+//
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+#if NET_2_0
+
+using System;
+using System.Collections;
+using System.Collections.Specialized;
+using System.Xml;
+using System.Xml.Query;
+using System.Xml.Schema;
+using Mono.Xml.XQuery;
+
+namespace Mono.Xml.XPath2
+{
+ internal abstract class XQueryModule
+ {
+ string version;
+ Prolog prolog;
+ IXmlNamespaceResolver nsResolver;
+
+ public string Version {
+ get { return version; }
+ set { version = value; }
+ }
+
+ public Prolog Prolog {
+ get { return prolog; }
+ set { prolog = value; }
+ }
+
+ public IXmlNamespaceResolver NSResolver {
+ get { return nsResolver; }
+ set { nsResolver = value; }
+ }
+ }
+
+ internal class XQueryMainModule : XQueryModule
+ {
+ ExprSequence queryBody;
+
+ public ExprSequence QueryBody {
+ get { return queryBody; }
+ set { queryBody = value; }
+ }
+ }
+
+ internal class XQueryLibraryModule : XQueryModule
+ {
+ ModuleDecl moduleDecl;
+
+ public ModuleDecl ModuleDecl {
+ get { return moduleDecl; }
+ set { moduleDecl = value; }
+ }
+ }
+
+ internal class ModuleDecl
+ {
+ string prefix;
+ string ns;
+
+ public string Prefix {
+ get { return prefix; }
+ set { prefix = value; }
+ }
+
+ public string Namespace {
+ get { return ns; }
+ set { ns = value; }
+ }
+ }
+
+ internal class Prolog
+ {
+ public Prolog ()
+ {
+ namespaceDecls = new StringDictionary ();
+ schemaImports = new SchemaImportCollection ();
+ moduleImports = new ModuleImportCollection ();
+ variables = new XQueryVariableTable ();
+ functions = new FunctionCollection ();
+ }
+
+ string version;
+ StringDictionary namespaceDecls;
+ XmlSpace xmlSpaceDecl;
+ XmlSpace constructorDecl;
+ string defaultElementNamespace;
+ string defaultFunctionNamespace;
+ string defaultCollation;
+ string baseUri;
+ bool defaultOrdered; // false by default
+ SchemaImportCollection schemaImports;
+ ModuleImportCollection moduleImports;
+ XQueryVariableTable variables;
+ XmlSchemaContentProcessing validationType;
+ FunctionCollection functions;
+
+ public string Version {
+ get { return version; }
+ set { version = value; }
+ }
+
+ public StringDictionary NamespaceDecls {
+ get { return namespaceDecls; }
+ }
+
+ public XmlSpace XmlSpace {
+ get { return xmlSpaceDecl; }
+ set { xmlSpaceDecl = value; }
+ }
+
+ public XmlSpace Constructor {
+ get { return constructorDecl; }
+ set { constructorDecl = value; }
+ }
+
+ public bool DefaultOrdered {
+ get { return defaultOrdered; }
+ set { defaultOrdered = value; }
+ }
+
+ public string DefaultElementNamespace {
+ get { return defaultElementNamespace; }
+ set { defaultElementNamespace = value; }
+ }
+
+ public string DefaultFunctionNamespace {
+ get { return defaultFunctionNamespace; }
+ set { defaultFunctionNamespace = value; }
+ }
+
+ public string DefaultCollation {
+ get { return defaultCollation; }
+ set { defaultCollation = value; }
+ }
+
+ public string BaseUri {
+ get { return baseUri; }
+ set { baseUri = value; }
+ }
+
+ public SchemaImportCollection SchemaImports {
+ get { return schemaImports; }
+ }
+
+ public ModuleImportCollection ModuleImports {
+ get { return moduleImports; }
+ }
+
+ public XQueryVariableTable Variables {
+ get { return variables; }
+ }
+
+ public XmlSchemaContentProcessing ValidationType {
+ get { return validationType; }
+ set { validationType = value; }
+ }
+
+ public FunctionCollection Functions {
+ get { return functions; }
+ }
+
+ public void Add (object item)
+ {
+ if (item is bool)
+ DefaultOrdered = (bool) item;
+ else if (item is XmlQualifiedName) {
+ XmlQualifiedName q = (XmlQualifiedName) item;
+ NamespaceDecls.Add (q.Name, q.Namespace);
+ } else if (item is XmlSpaceDecl) {
+ XmlSpace = ((XmlSpaceDecl) item).Value;
+ } else if (item is ConstructionDecl) {
+ Constructor = ((ConstructionDecl) item).Value;
+ } else if (item is SimplePrologContent) {
+ SimplePrologContent c = (SimplePrologContent) item;
+ string s = c.LiteralValue;
+ switch (c.Type) {
+ case PrologContentType.DefaultElementNamespace:
+ DefaultElementNamespace = s;
+ break;
+ case PrologContentType.DefaultFunctionNamespace:
+ DefaultFunctionNamespace = s;
+ break;
+ case PrologContentType.DefaultCollation:
+ DefaultCollation = s;
+ break;
+ case PrologContentType.BaseUri:
+ BaseUri = s;
+ break;
+ default:
+ throw new XmlQueryCompileException ("Invalid XQuery prolog content was found.");
+ }
+ } else if (item is SchemaImport) {
+ SchemaImports.Add (item as SchemaImport);
+ } else if (item is ModuleImport) {
+ ModuleImports.Add (item as ModuleImport);
+ } else if (item is XQueryVariable) {
+ XQueryVariable var = item as XQueryVariable;
+ Variables.Add (var);
+ } else if (item is XmlSchemaContentProcessing) {
+ ValidationType = (XmlSchemaContentProcessing) item;
+ } else if (item is FunctionDeclaration) {
+ Functions.Add (item as FunctionDeclaration);
+ } else
+ throw new XmlQueryCompileException ("Invalid XQuery prolog content item was found.");
+ }
+ }
+
+ class XmlSpaceDecl
+ {
+ public XmlSpace Value;
+
+ public XmlSpaceDecl (XmlSpace value)
+ {
+ Value = value;
+ }
+ }
+
+ class ConstructionDecl
+ {
+ public XmlSpace Value;
+
+ public ConstructionDecl (XmlSpace value)
+ {
+ Value = value;
+ }
+ }
+
+ public class ModuleImportCollection : CollectionBase
+ {
+ public void Add (ModuleImport import)
+ {
+ List.Add (import);
+ }
+ }
+
+ public class SchemaImportCollection : CollectionBase
+ {
+ public void Add (SchemaImport import)
+ {
+ List.Add (import);
+ }
+ }
+
+ public enum PrologContentType {
+ DefaultElementNamespace,
+ DefaultFunctionNamespace,
+ DefaultCollation,
+ BaseUri
+ }
+
+ public class SimplePrologContent
+ {
+ public SimplePrologContent (PrologContentType type, string literalValue)
+ {
+ this.type = type;
+ this.literalValue = literalValue;
+ }
+
+ PrologContentType type;
+ string literalValue;
+
+ public PrologContentType Type {
+ get { return type; }
+ set { type = value; }
+ }
+
+ public string LiteralValue {
+ get { return literalValue; }
+ set { literalValue = value; }
+ }
+ }
+
+ public abstract class AbstractImport
+ {
+ public AbstractImport (string prefix, string ns, ICollection locations)
+ {
+ this.prefix = prefix;
+ this.ns = ns;
+ this.locations = locations;
+ if (locations == null)
+ this.locations = new ArrayList (); // empty list
+ }
+
+ string prefix, ns;
+ ICollection locations;
+
+ public string Prefix {
+ get { return prefix; }
+ set { prefix = value; }
+ }
+
+ public string Namespace {
+ get { return ns; }
+ set { ns = value; }
+ }
+
+ public ICollection Locations {
+ get { return locations; }
+ set { locations = value != null ? value : new ArrayList (); }
+ }
+ }
+
+ public class SchemaImport : AbstractImport
+ {
+ public SchemaImport (string prefix, string ns, ICollection schemaLocations)
+ : base (prefix == "default element namespace" ? String.Empty : prefix, ns, schemaLocations)
+ {
+ // Prefix might 1) String.Empty for non-specified prefix,
+ // 2) "default element namespace" that is as is
+ // specified in xquery.
+ if (prefix == "default element namespace")
+ useDefaultElementNamespace = true;
+ }
+
+ bool useDefaultElementNamespace;
+
+ public bool UseDefaultElementNamespace {
+ get { return useDefaultElementNamespace; }
+ set { useDefaultElementNamespace = value; }
+ }
+ }
+
+ public class ModuleImport : AbstractImport
+ {
+ public ModuleImport (string prefix, string ns, ICollection moduleLocations)
+ : base (prefix, ns, moduleLocations)
+ {
+ }
+ }
+
+ public class XQueryVariableTable : DictionaryBase
+ {
+ public void Add (XQueryVariable decl)
+ {
+ Dictionary.Add (decl.Name, decl);
+ }
+
+ public ICollection Keys {
+ get { return Dictionary.Keys; }
+ }
+
+ public ICollection Values {
+ get { return Dictionary.Values; }
+ }
+
+ public XQueryVariable this [XmlQualifiedName name] {
+ get { return Dictionary [name] as XQueryVariable; }
+ }
+ }
+
+ public class XQueryVariable
+ {
+ public XQueryVariable (XmlQualifiedName name, SequenceType type, ExprSequence varBody)
+ {
+ this.name = name;
+ this.type = type;
+ this.varBody = varBody; // might be null (just declaration).
+ }
+
+ XmlQualifiedName name;
+ SequenceType type;
+ ExprSequence varBody;
+
+ public XmlQualifiedName Name {
+ get { return name; }
+ }
+
+ public SequenceType VariableType {
+ get { return type; }
+ }
+
+ public bool External {
+ get { return varBody == null; }
+ }
+
+ public ExprSequence VariableBody {
+ get { return varBody; }
+ }
+ }
+
+ internal class FunctionCollection : DictionaryBase
+ {
+ public void Add (FunctionDeclaration decl)
+ {
+ Dictionary.Add (decl.Name, decl);
+ }
+
+ public ICollection Keys {
+ get { return Dictionary.Keys; }
+ }
+
+ public ICollection Values {
+ get { return Dictionary.Values; }
+ }
+
+ public FunctionDeclaration this [XmlQualifiedName name] {
+ get { return Dictionary [name] as FunctionDeclaration; }
+ }
+ }
+
+ internal class FunctionDeclaration
+ {
+ public FunctionDeclaration (XmlQualifiedName name,
+ XQueryFunctionArgumentList parameters,
+ SequenceType type,
+ EnclosedExpr expr)
+ {
+ this.name = name;
+ this.parameters = parameters;
+ this.returnType = type;
+ this.funcBody = expr;
+ }
+
+ XmlQualifiedName name;
+ SequenceType returnType;
+ XQueryFunctionArgumentList parameters;
+ EnclosedExpr funcBody;
+
+ public XmlQualifiedName Name {
+ get { return name; }
+ }
+
+ public SequenceType ReturnType {
+ get { return returnType; }
+ }
+
+ public bool External {
+ get { return funcBody == null; }
+ }
+
+ public XQueryFunctionArgumentList Parameters {
+ get { return parameters; }
+ }
+
+ public EnclosedExpr FunctionBody {
+ get { return funcBody; }
+ }
+ }
+
+ public class XQueryFunctionArgumentList : CollectionBase
+ {
+ public void Add (XQueryFunctionArgument p)
+ {
+ List.Add (p);
+ }
+
+ public void Insert (int pos, XQueryFunctionArgument p)
+ {
+ List.Insert (pos, p);
+ }
+
+ public XQueryFunctionArgument this [int i] {
+ get { return (XQueryFunctionArgument) List [i]; }
+ }
+
+ public XQueryFunctionArgument [] ToArray ()
+ {
+ XQueryFunctionArgument [] arr = new XQueryFunctionArgument [List.Count];
+ List.CopyTo (arr, 0);
+ return arr;
+ }
+ }
+
+ public abstract class PragmaMUExtensionBase
+ {
+ XmlQualifiedName name;
+ string text;
+
+ protected PragmaMUExtensionBase (XmlQualifiedName name, string text)
+ {
+ this.name = name;
+ this.text = text;
+ }
+
+ public XmlQualifiedName Name {
+ get { return name; }
+ }
+
+ public string Text {
+ get { return text; }
+ }
+ }
+
+ public class Pragma : PragmaMUExtensionBase
+ {
+ public Pragma (XmlQualifiedName name, string text)
+ : base (name, text)
+ {
+ }
+ }
+
+ public class MUExtension : PragmaMUExtensionBase
+ {
+ public MUExtension (XmlQualifiedName name, string text)
+ : base (name, text)
+ {
+ }
+ }
+}
+
+#endif
diff --git a/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XQueryParser.jay b/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XQueryParser.jay
new file mode 100755
index 00000000000..f11635bfda2
--- /dev/null
+++ b/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XQueryParser.jay
@@ -0,0 +1,2535 @@
+%{
+//
+// XQueryParser.jay
+//
+// Author:
+// Atsushi Enomoto <atsushi@ximian.com>
+//
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+//
+// FIXME:
+// attribute value template
+// handle double literal
+//
+
+#if NET_2_0
+
+using System;
+using System.Collections;
+using System.IO;
+using System.Xml;
+using System.Xml.Query;
+using System.Xml.Schema;
+using System.Xml.XPath;
+using System.Security.Policy;
+using Mono.Xml.XPath2;
+using Mono.Xml.XQuery;
+using Mono.Xml;
+
+namespace Mono.Xml.XQuery.Parser
+{
+ internal class XQueryParser
+ {
+ // See also FunctionCall production rule.
+ static Hashtable reservedFunctionNames;
+
+ static XQueryParser ()
+ {
+ reservedFunctionNames = new Hashtable ();
+ reservedFunctionNames.Add ("attribute", "attribute");
+ reservedFunctionNames.Add ("comment", "comment");
+ reservedFunctionNames.Add ("document", "document");
+ reservedFunctionNames.Add ("element", "element");
+ reservedFunctionNames.Add ("empty", "empty");
+ reservedFunctionNames.Add ("if", "if");
+ reservedFunctionNames.Add ("item", "item");
+ reservedFunctionNames.Add ("node", "node");
+ reservedFunctionNames.Add ("processing-instruction", "processing-instruction");
+ reservedFunctionNames.Add ("text", "text");
+ reservedFunctionNames.Add ("type", "type");
+ reservedFunctionNames.Add ("typeswitch", "typeswitch");
+ }
+
+ public static XQueryModule Parse (TextReader reader)
+ {
+ return new XQueryParser ().RunParse (reader);
+ }
+
+ private XQueryTokenizer tokenizer;
+
+ private XQueryParser ()
+ {
+ }
+
+ // FIXME: we don't need Evidence here at all. It is used only
+ // to generate runnable IL (on loading resulting Assembly).
+ public XQueryModule RunParse (TextReader source)
+ {
+ tokenizer = null;
+ try {
+// debug = new yydebug.yyDebugSimple ();
+ tokenizer = new XQueryTokenizer (source);
+ XQueryModule mod = (XQueryModule) yyparse (tokenizer);
+ mod.NSResolver = tokenizer.NSResolver;
+ return mod;
+ } catch (yyParser.yyException ex) {
+ throw new XmlQueryCompileException (String.Format ("Tokenizer error at line {0}, column {1}: {2}", tokenizer.LineNumber, tokenizer.LinePosition, ex.Message), ex);
+ }
+ }
+
+ public XmlTypeCode GetAtomicTypeCode (XmlQualifiedName name)
+ {
+ if (name.Namespace == InternalPool.XdtNamespace) {
+ switch (name.Name) {
+ case "anyAtomicType":
+ return XmlTypeCode.AnyAtomicType;
+ case "dayTimeDuration":
+ return XmlTypeCode.DayTimeDuration;
+ case "item":
+ return XmlTypeCode.Item;
+ case "untypedAtomic":
+ return XmlTypeCode.UntypedAtomic;
+ case "yearMonthDuration":
+ return XmlTypeCode.YearMonthDuration;
+ }
+ } else if (name.Namespace == XmlSchema.Namespace) {
+ switch (name.Name) {
+ case "boolean":
+ return XmlTypeCode.Boolean;
+ case "byte":
+ return XmlTypeCode.Byte;
+ case "date":
+ return XmlTypeCode.Date;
+ case "dateTime":
+ return XmlTypeCode.DateTime;
+ case "decimal":
+ return XmlTypeCode.Decimal;
+ case "double":
+ return XmlTypeCode.Double;
+ case "duration":
+ return XmlTypeCode.Duration;
+ case "entity":
+ return XmlTypeCode.Entity;
+ case "float":
+ return XmlTypeCode.Float;
+ case "gDay":
+ return XmlTypeCode.GDay;
+ case "gMonth":
+ return XmlTypeCode.GMonth;
+ case "gMonthDay":
+ return XmlTypeCode.GMonthDay;
+ case "gYear":
+ return XmlTypeCode.GYear;
+ case "gYearMonth":
+ return XmlTypeCode.GYearMonth;
+ case "hexBinary":
+ return XmlTypeCode.HexBinary;
+ case "id":
+ return XmlTypeCode.Id;
+ case "idref":
+ return XmlTypeCode.Idref;
+ case "int":
+ return XmlTypeCode.Int;
+ case "integer":
+ return XmlTypeCode.Integer;
+ case "language":
+ return XmlTypeCode.Language;
+ case "long":
+ return XmlTypeCode.Long;
+ case "Name":
+ return XmlTypeCode.Name;
+ case "NCName":
+ return XmlTypeCode.NCName;
+ case "negativeInteger":
+ return XmlTypeCode.NegativeInteger;
+ case "NMTOKEN":
+ return XmlTypeCode.NmToken;
+ case "nonNegativeInteger":
+ return XmlTypeCode.NonNegativeInteger;
+ case "nonPositiveInteger":
+ return XmlTypeCode.NonPositiveInteger;
+ case "normalizedString":
+ return XmlTypeCode.NormalizedString;
+ case "NOTATION":
+ return XmlTypeCode.Notation;
+ case "positiveInteger":
+ return XmlTypeCode.PositiveInteger;
+ case "QName":
+ return XmlTypeCode.QName;
+ case "short":
+ return XmlTypeCode.Short;
+ case "string":
+ return XmlTypeCode.String;
+ case "time":
+ return XmlTypeCode.Time;
+ case "token":
+ return XmlTypeCode.Token;
+ case "unsignedByte":
+ return XmlTypeCode.UnsignedByte;
+ case "unsignedInt":
+ return XmlTypeCode.UnsignedInt;
+ case "unsignedLong":
+ return XmlTypeCode.UnsignedLong;
+ case "unsignedShort":
+ return XmlTypeCode.UnsignedShort;
+ }
+ }
+ throw new XmlQueryCompileException (String.Format ("Unexpected type name was specified as atomic type: {0}", name));
+ }
+
+%}
+
+/* --------------------------------------------------------
+ Tokens
+-------------------------------------------------------- */
+
+/* These are for numbers */
+//%token SMALL_E //"e"
+//%token LARGE_E //"E"
+
+%token DOT "."
+%token DOT2 ".."
+%token SEMICOLON ";"
+%token OPEN_PAREN "("
+%token OPEN_PAREN_COLON "(:"
+%token PRAGMA_OPEN "(::"
+%token CLOSE_PAREN ")"
+%token COLON ":"
+%token COLON2 "::"
+%token PRAGMA_CLOSE "::)"
+%token CLOSE_PAREN_COLON ":)"
+%token COLON_EQUAL ":="
+%token OPEN_BRACKET "["
+%token CLOSE_BRACKET "]"
+%token OPEN_CURLY "{"
+%token CLOSE_CURLY "}"
+%token COMMA ","
+%token DOLLAR "$"
+%token EQUAL "="
+%token NOT_EQUAL "!="
+%token LESSER "<"
+%token LESSER2 "<<"
+%token LESSER_EQUAL "<="
+%token GREATER ">"
+%token GREATER2 ">>"
+%token GREATER_EQUAL ">="
+%token BAR "|"
+%token ASTERISK "*"
+%token PLUS "+"
+%token MINUS "-"
+%token SLASH "/"
+%token SLASH2 "//"
+%token QUESTION "?"
+
+
+%token XQUERY //"xquery"
+%token VERSION //"version"
+%token PRAGMA //"pragma"
+%token EXTENSION //"extension"
+%token MODULE //"module"
+%token NAMESPACE //"namespace"
+%token DECLARE //"declare"
+%token XMLSPACE //"xmlspace"
+%token PRESERVE //"preserve"
+%token STRIP //"strip"
+%token DEFAULT //"default"
+%token DOCUMENT_NODE //"document-node"
+%token DOCUMENT //"document"
+%token ELEMENT //"element"
+%token ATTRIBUTE //"attribute"
+%token PROCESSING_INSTRUCTION //"processing-instruction"
+%token COMMENT //"comment"
+%token TEXT //"text"
+%token NODE //"node"
+%token FUNCTION //"function"
+%token COLLATION //"collation"
+%token CONSTRUCTION //"construction"
+%token ORDERING //"ordering"
+%token ORDERED //"ordered"
+%token UNORDERED //"unordered"
+%token BASEURI //"base-uri"
+%token IMPORT //"import"
+%token SCHEMA //"schema"
+%token AT //"at"
+%token VARIABLE //"variable"
+%token AS //"as"
+%token EXTERNAL //"external"
+%token VALIDATION //"validation"
+%token LAX //"lax"
+%token STRICT //"strict"
+%token SKIP //"skip"
+%token RETURN //"return"
+%token FOR //"for"
+%token LET //"let"
+%token IN //"in"
+%token WHERE //"where"
+%token ORDER //"order"
+%token BY //"by"
+%token STABLE //"stable"
+%token ASCENDING //"ascending"
+%token DESCENDING //"descending"
+%token EMPTY //"empty"
+%token GREATEST //"greatest"
+%token LEAST //"least"
+%token SOME //"some"
+%token EVERY //"every"
+%token SATISFIES //"satisfies"
+%token IS //"is"
+%token TO //"to"
+%token EQ //"eq"
+%token NE //"ne"
+%token LT //"lt"
+%token LE //"le"
+%token GT //"gt"
+%token GE //"ge"
+%token AND //"and"
+%token OR //"or"
+%token INSTANCE //"instance"
+%token OF //"of"
+%token IF //"if"
+%token THEN //"then"
+%token ELSE //"else"
+%token TYPESWITCH //"typeswitch"
+%token CASE //"case"
+%token TREAT //"treat"
+%token CASTABLE //"castable"
+%token CAST //"as"
+%token DIV //"div"
+%token IDIV //"idiv"
+%token MOD //"mod"
+%token UNION //"union"
+%token INTERSECT //"intersect"
+%token EXCEPT //"except"
+%token VALIDATE //"validate"
+%token CONTEXT //"context"
+%token NILLABLE //"nillable"
+%token ITEM //"item"
+
+
+%token GLOBAL //"global"
+%token TYPE //"type"
+
+%token CHILD //"child"
+%token DESCENDANT //"descendant"
+%token ATTRIBUTE //"attribute"
+%token SELF //"self"
+%token DESCENDANT_OR_SELF //"descendant-or-self"
+%token FOLLOWING_SIBLING //"following-sibling"
+%token FOLLOWING //"following"
+%token PARENT //"parent"
+%token ANCESTOR //"ancestor"
+%token PRECEDING_SIBLING //"preceding-sibling"
+%token PRECEDING //"preceding"
+%token ANCESTOR_OR_SELF //"ancestor-or-self"
+
+
+
+%token QNAME
+%token NCNAME
+%token WILD_LOCALNAME
+%token WILD_PREFIX
+
+%token STRING_LITERAL
+%token DECIMAL_LITERAL
+%token DOUBLE_LITERAL
+
+%token PRAGMA_CONTENTS // characters until "::)"
+
+
+%token PREDEFINED_ENTITY_REF
+%token CHAR_REF
+
+// Used only inside Constructor
+%token XML_COMMENT_START // "<!--"
+%token XML_COMMENT_TO_END // XML comment content immediate before "-->"
+%token XML_PI_START // "<?"
+%token XML_PI_TO_END // PI content immediate before "?>"
+%token XML_CDATA_START // <![CDATA[
+%token XML_CDATA_TO_END // CDATA section content immediate before "]]>"
+%token EMPTY_TAG_CLOSE // "/>"
+%token END_TAG_START // "</". Its appearance depends on the context
+%token ATT_VALUE_LITERAL
+%token ELEM_CONTENT_LITERAL
+%token EXT_CONTENT
+%token APOS "'"
+//%token APOS2 "''"
+%token QUOT //""""
+//%token QUOT2 //""""""
+
+%start Module
+
+%%
+
+/* --------------------------------------------------------
+ Modules and Prologs
+-------------------------------------------------------- */
+
+Module // returns Module
+ : VersionDecl MainModule
+ {
+ string version = (string) $1;
+ XQueryMainModule module = (XQueryMainModule) $2;
+ module.Version = version;
+ $$ = module;
+ }
+ | VersionDecl LibraryModule
+ {
+ string version = (string) $1;
+ XQueryLibraryModule module = (XQueryLibraryModule) $2;
+ $$ = module;
+ }
+ ;
+
+VersionDecl // returns string
+ : // empty
+ {
+ $$ = null;
+ }
+ | XQUERY VERSION STRING_LITERAL {
+ tokenizer.State = ParseState.Operator;
+ } SEMICOLON {
+ tokenizer.State = ParseState.Default;
+ }
+ {
+ $$ = (string) $3;
+ }
+ ;
+
+MainModule // returns MainModule
+ : Prolog QueryBody
+ {
+ Prolog prolog = (Prolog) $1;
+ ExprSequence body = (ExprSequence) $2;
+
+ XQueryMainModule mod = new XQueryMainModule ();
+ mod.Prolog = prolog;
+ mod.QueryBody = body;
+ $$ = mod;
+ }
+ ;
+
+LibraryModule // returns LibraryModule
+ : ModuleDecl Prolog
+ {
+ XQueryLibraryModule mod = new XQueryLibraryModule ();
+ mod.ModuleDecl = (ModuleDecl) $1;
+ mod.Prolog = (Prolog) $2;
+ $$ = mod;
+ }
+ ;
+
+ModuleDecl // returns ModuleDecl
+ : MODULE NAMESPACE {
+ tokenizer.State = ParseState.NamespaceDecl;
+ } NCName EQUAL STRING_LITERAL {
+ tokenizer.State = ParseState.Default;
+ } SEMICOLON
+ {
+ ModuleDecl decl = new ModuleDecl ();
+ decl.Prefix = (string) $4;
+ decl.Namespace = (string) $6;
+ tokenizer.AddNamespace (decl.Prefix, decl.Namespace);
+ $$ = decl;
+ }
+ ;
+
+Prolog
+ : // empty
+ {
+ $$ = new Prolog ();
+ }
+ | PrologContent SEMICOLON Prolog
+ {
+ Prolog p = (Prolog) $3;
+ p.Add ($1);
+ $$ = p;
+ }
+ ;
+
+PrologContent
+ : Setter
+ | DeclarationOrImport
+ ;
+
+// FIXME: this production rule is the right one, but it brings
+// major shift/reduce conflicts.
+/*
+Prolog // returns Prolog
+ : Setters DeclarationsAndImports
+ {
+ Prolog p = (Prolog) $1;
+ ArrayList al = (ArrayList) $2;
+ if (al != null) {
+ foreach (object o in al)
+ p.Add (o);
+ }
+ $$ = p;
+ }
+ ;
+
+Setters // returns Prolog
+ : // empty
+ {
+ $$ = new Prolog ();
+ }
+ | Setter SEMICOLON Setters
+ {
+ Prolog p = (Prolog) $3;
+ p.Add ($1);
+ $$ = p;
+ }
+ ;
+
+DeclarationsAndImports // returns ArrayList
+ : // empty
+ {
+ $$ = null;
+ }
+ | DeclarationOrImport SEMICOLON DeclarationsAndImports
+ {
+ ArrayList al = (ArrayList) $3;
+ if (al == null)
+ al = new ArrayList ();
+ al.Add ($1);
+ $$ = al;
+ }
+ ;
+
+*/
+
+Setter // returns object
+ : XmlSpaceDecl // XmlSpaceDecl
+ | DefaultCollationDecl // SimplePrologContent
+ | BaseURIDecl // SimplePrologContent
+ | ConstructionDecl // ConstuctionDecl
+ | DefaultNamespaceDecl // SimplePrologContent
+ | DefaultOrderingDecl // bool
+ ;
+
+DeclarationOrImport // returns object
+ : SchemaImport
+ | ModuleImport
+ | NamespaceDecl
+ | VarDecl
+ | FunctionDecl
+ ;
+
+NamespaceDecl // returns XmlQualifiedName
+ : DECLARE NAMESPACE {
+ tokenizer.State = ParseState.NamespaceDecl;
+ } NCName EQUAL STRING_LITERAL {
+ tokenizer.State = ParseState.Default;
+ }
+ {
+ XmlQualifiedName name = new XmlQualifiedName ((string) $4, (string) $6);
+ tokenizer.AddNamespace (name.Name, name.Namespace);
+ $$ = name;
+ }
+ ;
+
+XmlSpaceDecl // returns XmlSpaceDecl
+ : DECLARE XMLSPACE {
+ tokenizer.State = ParseState.XmlSpaceDecl;
+ } PRESERVE {
+ tokenizer.State = ParseState.Default;
+ }
+ {
+ $$ = new XmlSpaceDecl (XmlSpace.Preserve);
+ }
+ | DECLARE XMLSPACE {
+ tokenizer.State = ParseState.XmlSpaceDecl;
+ } STRIP {
+ tokenizer.State = ParseState.Default;
+ }
+ {
+ $$ = new XmlSpaceDecl (XmlSpace.Default);
+ }
+ ;
+
+ConstructionDecl // returns ConstructionDecl
+ : DECLARE CONSTRUCTION {
+ tokenizer.State = ParseState.Operator;
+ } PRESERVE {
+ tokenizer.State = ParseState.Default;
+ }
+ {
+ $$ = new ConstructionDecl (XmlSpace.Preserve);
+ }
+ | DECLARE CONSTRUCTION {
+ tokenizer.State = ParseState.Operator;
+ } STRIP {
+ tokenizer.State = ParseState.Default;
+ }
+ {
+ $$ = new ConstructionDecl (XmlSpace.Default);
+ }
+ ;
+
+DefaultNamespaceDecl // returns SimplePrologContent
+ : DECLARE DEFAULT ELEMENT {
+ tokenizer.State = ParseState.NamespaceKeyword;
+ } NAMESPACE {
+ tokenizer.State = ParseState.NamespaceDecl;
+ } STRING_LITERAL {
+ tokenizer.State = ParseState.Default;
+ }
+ {
+ tokenizer.AddNamespace (String.Empty, (string) $7);
+ $$ = new SimplePrologContent (PrologContentType.DefaultElementNamespace, (string) $7);
+ }
+ | DECLARE DEFAULT FUNCTION {
+ tokenizer.State = ParseState.NamespaceKeyword;
+ } NAMESPACE {
+ tokenizer.State = ParseState.NamespaceDecl;
+ } STRING_LITERAL {
+ tokenizer.State = ParseState.Default;
+ }
+ {
+ tokenizer.DefaultFunctionNamespace = (string) $5;
+ $$ = new SimplePrologContent (PrologContentType.DefaultFunctionNamespace, (string) $5);
+ }
+ ;
+
+DefaultCollationDecl // returns SimplePrologContent
+ : DECLARE DEFAULT COLLATION {
+ tokenizer.State = ParseState.NamespaceDecl;
+ } STRING_LITERAL {
+ tokenizer.State = ParseState.Default;
+ }
+ {
+ $$ = new SimplePrologContent (PrologContentType.DefaultCollation, (string) $4);
+ }
+ ;
+
+DefaultOrderingDecl // returns bool
+ : DECLARE DEFAULT ORDERING {
+ tokenizer.State = ParseState.Operator;
+ } ORDERED {
+ tokenizer.State = ParseState.Default;
+ }
+ {
+ $$ = true;
+ }
+ | DECLARE DEFAULT ORDERING {
+ tokenizer.State = ParseState.Operator;
+ } UNORDERED {
+ tokenizer.State = ParseState.Default;
+ }
+ {
+ $$ = false;
+ }
+ ;
+
+BaseURIDecl // returns SimplePrologContent
+ : DECLARE BASEURI {
+ tokenizer.State = ParseState.NamespaceDecl;
+ } STRING_LITERAL {
+ tokenizer.State = ParseState.Default;
+ }
+ {
+ $$ = new SimplePrologContent (PrologContentType.BaseUri, (string) $3);
+ }
+ ;
+
+SchemaImport // returns SchemaImport
+ : IMPORT SCHEMA {
+ tokenizer.State = ParseState.NamespaceKeyword;
+ } OptionalSchemaPrefix STRING_LITERAL {
+ tokenizer.State = ParseState.Default;
+ } OptionalLocations
+ {
+ if ($4 != null)
+ tokenizer.AddNamespace ((string) $4, (string) $5);
+ $$ = new SchemaImport ((string) $4, (string) $5, (ICollection) $7);
+ }
+ ;
+
+OptionalSchemaPrefix // returns string or null
+ : // empty
+ {
+ $$ = null;
+ }
+ | SchemaPrefix
+ ;
+
+SchemaPrefix // returns string
+ : NAMESPACE {
+ tokenizer.State = ParseState.NamespaceDecl;
+ } NCName EQUAL {
+ }
+ {
+ $$ = (string) $3;
+ }
+ | DEFAULT ELEMENT NAMESPACE {
+ tokenizer.State = ParseState.NamespaceDecl;
+ }
+ {
+ $$ = "";
+ }
+ ;
+
+ModuleImport // returns ModuleImport
+ : IMPORT MODULE {
+ tokenizer.State = ParseState.NamespaceKeyword;
+ } OptionalModuleNamespace STRING_LITERAL {
+ tokenizer.State = ParseState.Default;
+ } OptionalLocations
+ {
+ $$ = new ModuleImport ((string) $4, (string) $5, (ICollection) $7);
+ tokenizer.AddNamespace ((string) $4, (string) $5);
+ }
+ ;
+
+OptionalModuleNamespace // returns string
+ : // empty
+ {
+ $$ = String.Empty;
+ }
+ | NAMESPACE {
+ tokenizer.State = ParseState.NamespaceDecl;
+ } NCName EQUAL
+ {
+ $$ = (string) $3;
+ }
+ ;
+
+OptionalLocations // returns ArrayList or null
+ : // empty
+ {
+ $$ = null;
+ }
+ | AT STRING_LITERAL AdditionalLocations
+ {
+ ArrayList al = (ArrayList) $3;
+ if (al != null)
+ al = new ArrayList ();
+ al.Add ((string) $2);
+ $$ = al;
+ }
+ ;
+
+AdditionalLocations // returns ArrayList or null
+ : // empty
+ {
+ $$ = null;
+ }
+ | COMMA STRING_LITERAL AdditionalLocations
+ {
+ ArrayList al = (ArrayList) $3;
+ if (al == null)
+ al = new ArrayList ();
+ al.Add ((string) $2);
+ $$ = al;
+ }
+ ;
+
+VarDecl // returns VariableDeclaration
+ : DECLARE VARIABLE DOLLAR {
+ tokenizer.PushState (ParseState.Default);
+ tokenizer.State = ParseState.VarName;
+ } VarName {
+ tokenizer.State = ParseState.Operator;
+ } OptionalTypeDeclaration VarDeclBody
+ {
+ $$ = new XQueryVariable ((XmlQualifiedName) $4, (SequenceType) $5, (ExprSequence) $6);
+ }
+ ;
+
+VarDeclBody // returns ExprSequence or null
+ : OPEN_CURLY {
+ tokenizer.State = ParseState.Default;
+ } Expr CloseCurly
+ {
+ $$ = $2;
+ }
+ | EXTERNAL {
+ // LAMESPEC: This state transition is not described in XQuery 1.0 spec
+ tokenizer.PopState ();
+ }
+ {
+ $$ = null;
+ }
+ ;
+
+VarName // returns XmlQualifiedName
+ : QName {
+ tokenizer.State = ParseState.Operator;
+ }
+ {
+ $$ = $1;
+ }
+ ;
+
+OptionalTypeDeclaration // returns SequenceType or null
+ : // empty
+ {
+ $$ = null;
+ }
+ | TypeDeclaration
+ ;
+
+TypeDeclaration // returns SequenceType
+ : AS { // Note that this transition applies only at Operator state.
+ tokenizer.State = ParseState.ItemType;
+ } SequenceType
+ {
+ $$ = $2;
+ }
+ ;
+
+FunctionDecl // returns FunctionDeclaration
+ : DECLARE FUNCTION {
+ tokenizer.PushState (ParseState.Default);
+ tokenizer.State = ParseState.Default;
+ } QName OPEN_PAREN OptionalParamList CLOSE_PAREN {
+ tokenizer.State = ParseState.Operator;
+ } OptionalTypeDeclaration FunctionBody
+ {
+ $$ = new FunctionDeclaration (
+ (XmlQualifiedName) $4,
+ (XQueryFunctionArgumentList) $6,
+ (SequenceType) $9,
+ (EnclosedExpr) $10);
+ }
+ ;
+
+FunctionBody // returns EnclosedExpr or null
+ : EnclosedExpr
+ | EXTERNAL
+ {
+ $$ = null;
+ }
+ ;
+
+SequenceType // returns SequenceType
+ : ItemType OptionalOccurenceIndicator
+ {
+ $$ = new SequenceType ((ItemType) $1, (Occurence) $2);
+ }
+ | EMPTY OPEN_PAREN CLOSE_PAREN {
+ tokenizer.State = ParseState.Operator;
+ }
+ {
+ $$ = SequenceType.Create (XmlTypeCode.None, Occurence.One);
+ }
+ ;
+
+OptionalOccurenceIndicator // returns Occurence
+ : // empty
+ {
+ $$ = Occurence.One;
+ }
+ | OccurenceIndicator
+ ;
+
+OccurenceIndicator // returns Occurence
+ : QUESTION
+ {
+ $$ = Occurence.Optional;
+ }
+ | ASTERISK
+ {
+ $$ = Occurence.ZeroOrMore;
+ }
+ | PLUS
+ {
+ $$ = Occurence.OneOrMore;
+ }
+ ;
+
+OptionalParamList // returns XQueryFunctionArgumentList
+ : // empty
+ {
+ $$ = new XQueryFunctionArgumentList ();
+ }
+ | ParamList
+ ;
+
+ParamList // returns XQueryFunctionArgumentList
+ : Param
+ {
+ XQueryFunctionArgumentList pl = new XQueryFunctionArgumentList ();
+ pl.Add ((XQueryFunctionArgument) $1);
+ $$ = pl;
+ }
+ | Param COMMA ParamList
+ {
+ XQueryFunctionArgumentList pl = (XQueryFunctionArgumentList) $3;
+ pl.Insert (0, (XQueryFunctionArgument) $1);
+ $$ = pl;
+ }
+ ;
+
+Param // returns XQueryFunctionArgument
+ : DOLLAR {
+ tokenizer.State = ParseState.VarName;
+ } VarName {
+ tokenizer.State = ParseState.Operator;
+ } OptionalTypeDeclaration
+ {
+ $$ = new XQueryFunctionArgument ((XmlQualifiedName) $3, (SequenceType) $5);
+ }
+ ;
+
+QueryBody
+ : Expr
+ ;
+
+
+/* --------------------------------------------------------
+ Expressions
+-------------------------------------------------------- */
+
+Expr // returns ExprSequence
+ : ExprSequence
+ {
+ ExprSequence seq = (ExprSequence) $1;
+ $$ = seq;
+ }
+ ;
+
+ExprSequence // returns ExprSequence
+ : ExprSingle
+ {
+ ExprSequence seq = new ExprSequence ();
+ seq.Add ((ExprSingle) $1);
+ $$ = seq;
+ }
+ | ExprSingle COMMA ExprSequence
+ {
+ ExprSequence seq = (ExprSequence) $3;
+ seq.Insert (0, (ExprSingle) $1);
+ $$ = seq;
+ }
+ ;
+
+ExprSingle // returns ExprSingle
+ : FLWORExpr
+ | QuantifiedExpr
+ | TypeswitchExpr
+ | IfExpr
+ | OrExpr
+ ;
+
+/* -------------------------------------
+ FLWORExpr
+------------------------------------- */
+
+FLWORExpr // returns FLWORExpr
+ : RepeatedForLetClause OptionalWhereClause OptionalOrderByClause RETURN {
+ tokenizer.State = ParseState.Default;
+ } ExprSingle
+ {
+ ForLetClauseCollection col = (ForLetClauseCollection) $1;
+ $$ = new FLWORExpr (col, (ExprSequence) $2, (OrderSpecList) $3, (ExprSingle) $6);
+ }
+ ;
+
+RepeatedForLetClause // returns ForLetClauseCollection
+ : ForLetClause
+ {
+ ForLetClauseCollection col = new ForLetClauseCollection ();
+ col.Add ((ForLetClause) $1);
+ $$ = col;
+ }
+ | ForLetClause RepeatedForLetClause
+ {
+ ForLetClauseCollection col = (ForLetClauseCollection) $2;
+ col.Insert (0, (ForLetClause) $1);
+ $$ = col;
+ }
+ ;
+
+ForLetClause // returns ForLetClause
+ : ForClause
+ | LetClause
+ ;
+
+OptionalWhereClause // returns ExprSequence or null
+ : // empty
+ {
+ $$ = null;
+ }
+ | WhereClause
+ ;
+
+OptionalOrderByClause
+ : // empty
+ {
+ $$ = null;
+ }
+ | OrderByClause
+ ;
+
+ForClause // returns ForClause
+ : FOR ForBody
+ {
+ ForClause fc = (ForClause) $2;
+ $$ = fc;
+ }
+ ;
+
+ForBody
+ : ForSingleBody
+ {
+ ForClause fc = new ForClause ();
+ fc.Add ((ForSingleBody) $1);
+ $$ = fc;
+ }
+ | ForSingleBody COMMA ForBody
+ {
+ ForClause fc = (ForClause) $3;
+ fc.Insert (0, (ForSingleBody) $1);
+ $$ = fc;
+ }
+ ;
+
+ForSingleBody // returns ForSingleBody
+ : DOLLAR {
+ tokenizer.State = ParseState.VarName;
+ } VarName {
+ tokenizer.State = ParseState.Operator;
+ } OptionalTypeDeclaration OptionalPositionalVar IN {
+ tokenizer.State = ParseState.Default;
+ } ExprSingle
+ {
+ $$ = new ForSingleBody ((XmlQualifiedName) $3, (SequenceType) $5, (XmlQualifiedName) $6, (ExprSingle) $9);
+ }
+ ;
+
+LetClause
+ : LET LetBody
+ {
+ LetClause let = (LetClause) $2;
+ $$ = let;
+ }
+ ;
+
+LetBody
+ : LetSingleBody
+ {
+ LetClause lc = new LetClause ();
+ lc.Add ((LetSingleBody) $1);
+ $$ = lc;
+ }
+ | LetSingleBody COMMA LetBody
+ {
+ LetClause let = (LetClause) $3;
+ let.Insert (0, (LetSingleBody) $1);
+ $$ = let;
+ }
+
+LetSingleBody
+ : DOLLAR {
+ tokenizer.State = ParseState.VarName;
+ } VarName {
+ tokenizer.State = ParseState.Operator;
+ } OptionalTypeDeclaration COLON_EQUAL {
+ tokenizer.State = ParseState.Default;
+ } ExprSingle
+ {
+ $$ = new LetSingleBody ((XmlQualifiedName) $3, (SequenceType) $5, (ExprSingle) $8);
+ }
+ ;
+
+OptionalPositionalVar // returns XmlQualifiedName
+ : // empty
+ {
+ $$ = XmlQualifiedName.Empty;
+ }
+ | PositionalVar
+ ;
+
+PositionalVar
+ : AT {
+ tokenizer.State = ParseState.Default;
+ } DOLLAR {
+ tokenizer.State = ParseState.VarName;
+ } VarName {
+ tokenizer.State = ParseState.Operator;
+ }
+ {
+ $$ = $5;
+ }
+ ;
+
+WhereClause // returns ExprSequence
+ : WHERE {
+ tokenizer.State = ParseState.Default;
+ } Expr
+ {
+ $$ = $3;
+ }
+ ;
+
+OrderByClause // returns OrderSpecList
+ : ORDER BY {
+ tokenizer.State = ParseState.Default;
+ } OrderSpecList
+ {
+ OrderSpecList l = (OrderSpecList) $4;
+ $$ = l;
+ }
+ | STABLE ORDER BY {
+ tokenizer.State = ParseState.Default;
+ } OrderSpecList
+ {
+ OrderSpecList l = (OrderSpecList) $5;
+ l.IsStable = true;
+ $$ = l;
+ }
+ ;
+
+OrderSpecList // returns OrderSpecList
+ : OrderSpec
+ {
+ OrderSpecList osl = new OrderSpecList ();
+ osl.Add ((OrderSpec) $1);
+ $$ = osl;
+ }
+ | OrderSpec COMMA OrderSpecList
+ {
+ OrderSpecList l = (OrderSpecList) $3;
+ l.Insert (0, (OrderSpec) $1);
+ $$ = l;
+ }
+ ;
+
+OrderSpec // returns OrderSpec
+ : ExprSingle OrderModifier
+ {
+ $$ = new OrderSpec ((ExprSingle) $1, (OrderModifier) $2);
+ }
+ ;
+
+OrderModifier
+ : OrderSpecBase OrderEmptyHandling OptionalCollation
+ {
+ $$ = new OrderModifier ((XmlSortOrder) $1, (XmlSortOrder) $2, (string) $3);
+ }
+ ;
+
+OrderSpecBase // returns XmlSortOrder
+ : // empty
+ {
+ $$ = XmlSortOrder.Ascending;
+ }
+ | ASCENDING
+ {
+ $$ = XmlSortOrder.Ascending;
+ }
+ | DESCENDING
+ {
+ $$ = XmlSortOrder.Descending;
+ }
+ ;
+
+/* FIXME: check if it is correct (especially empty case) */
+OrderEmptyHandling // returns XmlSortOrder
+ : // empty
+ {
+ $$ = XmlSortOrder.Ascending;
+ }
+ | EMPTY GREATEST
+ {
+ $$ = XmlSortOrder.Ascending;
+ }
+ | EMPTY LEAST
+ {
+ $$ = XmlSortOrder.Descending;
+ }
+ ;
+
+OptionalCollation // returns string
+ : // empty
+ {
+ $$ = null;
+ }
+ | COLLATION STRING_LITERAL
+ {
+ $$ = $2;
+ }
+ ;
+
+/* -------------------------------------
+ QuantifiedExpr
+------------------------------------- */
+
+QuantifiedExpr
+ : SOME QuantifiedExprBody SATISFIES ExprSingle
+ {
+ QuantifiedExprBodyList l = (QuantifiedExprBodyList) $2;
+ $$ = new QuantifiedExpr (false, l, (ExprSingle) $4);
+ }
+ | EVERY QuantifiedExprBody SATISFIES ExprSingle
+ {
+ QuantifiedExprBodyList l = (QuantifiedExprBodyList) $2;
+ $$ = new QuantifiedExpr (true, l, (ExprSingle) $4);
+ }
+ ;
+
+QuantifiedExprBody
+ : SingleQuantifiedExprBody
+ {
+ QuantifiedExprBodyList l = new QuantifiedExprBodyList ();
+ l.Add ((QuantifiedExprBody) $1);
+ $$ = l;
+ }
+ | SingleQuantifiedExprBody COMMA QuantifiedExprBody
+ {
+ QuantifiedExprBodyList l = (QuantifiedExprBodyList) $3;
+ l.Insert (0, (QuantifiedExprBody) $1);
+ $$ = l;
+ }
+ ;
+
+SingleQuantifiedExprBody // returns QuantifiedExprBody
+ : DOLLAR {
+ tokenizer.State = ParseState.VarName;
+ } VarName {
+ tokenizer.State = ParseState.Operator;
+ } OptionalTypeDeclaration IN {
+ tokenizer.State = ParseState.Default;
+ } ExprSingle
+ {
+ $$ = new QuantifiedExprBody ((XmlQualifiedName) $3, (SequenceType) $5, (ExprSingle) $8);
+ }
+ ;
+
+/* -------------------------------------
+ TypeswitchExpr
+------------------------------------- */
+
+TypeswitchExpr // returns TypeswitchExpr
+ : TYPESWITCH OPEN_PAREN {
+ tokenizer.PushState (ParseState.Operator);
+ tokenizer.State = ParseState.Default;
+ } Expr CLOSE_PAREN {
+ tokenizer.State = ParseState.Operator;
+ } RepeatedCaseClause DEFAULT OptionalVarSpec RETURN {
+ tokenizer.State = ParseState.Default;
+ } ExprSingle
+ {
+ $$ = new TypeswitchExpr ((ExprSequence) $4, (CaseClauseList) $7, (XmlQualifiedName) $9, (ExprSingle) $12);
+ }
+ ;
+
+RepeatedCaseClause // returns CaseClauseList
+ : CaseClause
+ {
+ CaseClauseList ccl = new CaseClauseList ();
+ ccl.Add ((CaseClause) $1);
+ $$ = ccl;
+ }
+ | CaseClause RepeatedCaseClause
+ {
+ CaseClauseList l = (CaseClauseList) $2;
+ l.Add ((CaseClause) $1);
+ $$ = l;
+ }
+ ;
+
+CaseClause // returns CaseClause
+ : CASE {
+ tokenizer.State = ParseState.ItemType;
+ } SequenceType RETURN {
+ tokenizer.State = ParseState.Default;
+ } ExprSingle
+ {
+ $$ = new CaseClause ((SequenceType) $3, (ExprSingle) $6, XmlQualifiedName.Empty);
+ }
+ | CASE {
+ tokenizer.State = ParseState.ItemType;
+ } DOLLAR {
+ tokenizer.State = ParseState.VarName;
+ } VarName {
+ tokenizer.State = ParseState.Operator;
+ } AS {
+ tokenizer.State = ParseState.ItemType;
+ } SequenceType RETURN {
+ tokenizer.State = ParseState.Default;
+ } ExprSingle
+ {
+ $$ = new CaseClause ((SequenceType) $9, (ExprSingle) $12, (XmlQualifiedName) $5);
+ }
+ ;
+
+OptionalVarSpec // returns XmlQualifiedName
+ : // empty
+ {
+ $$ = XmlQualifiedName.Empty;
+ }
+ | DOLLAR VarName
+ {
+ $$ = (XmlQualifiedName) $2;
+ }
+ ;
+
+/* -------------------------------------
+ IfExpr
+------------------------------------- */
+
+IfExpr
+ : IF OPEN_PAREN Expr CLOSE_PAREN {
+ tokenizer.State = ParseState.Operator;
+ } THEN {
+ tokenizer.State = ParseState.Default;
+ } ExprSingle ELSE {
+ tokenizer.State = ParseState.Default;
+ } ExprSingle
+ {
+ $$ = new IfExpr ((ExprSequence) $3, (ExprSingle) $8, (ExprSingle) $11);
+ }
+ ;
+
+/* -------------------------------------
+ Logical Expressions
+------------------------------------- */
+
+OrExpr
+ : AndExpr
+ | AndExpr OR {
+ tokenizer.State = ParseState.Default;
+ } OrExpr
+ {
+ $$ = new OrExpr ((ExprSingle) $1, (ExprSingle) $4);
+ }
+ ;
+
+AndExpr
+ : InstanceOfExpr
+ | InstanceOfExpr AND {
+ tokenizer.State = ParseState.Default;
+ } AndExpr
+ {
+ $$ = new AndExpr ((ExprSingle) $1, (ExprSingle) $4);
+ }
+ ;
+
+/* -------------------------------------
+ Typed Expressions
+------------------------------------- */
+
+InstanceOfExpr
+ : TreatExpr
+ | TreatExpr INSTANCE OF {
+ tokenizer.State = ParseState.ItemType;
+ } SequenceType
+ {
+ $$ = new InstanceOfExpr ((ExprSingle) $1, (SequenceType) $5);
+ }
+ ;
+
+TreatExpr
+ : CastableExpr
+ | CastableExpr TREAT AS {
+ tokenizer.State = ParseState.ItemType;
+ } SequenceType
+ {
+ $$ = new TreatExpr ((ExprSingle) $1, (SequenceType) $5);
+ }
+ ;
+
+CastableExpr
+ : CastExpr
+ | CastExpr CASTABLE AS {
+ tokenizer.State = ParseState.ItemType;
+ } AtomicType OptionalQuestion
+ {
+ $$ = new CastableExpr ((ExprSingle) $1, (XmlTypeCode) $5, (bool)$6);
+ }
+ ;
+
+OptionalQuestion
+ : // empty
+ {
+ $$ = false;
+ }
+ | QUESTION
+ {
+ $$ = true;
+ }
+ ;
+
+CastExpr
+ : ComparisonExpr
+ | ComparisonExpr CAST AS {
+ tokenizer.State = ParseState.ItemType;
+ } AtomicType OptionalQuestion
+ {
+ $$ = new CastExpr ((ExprSingle) $1, (XmlTypeCode) $5, (bool) $6);
+ }
+ ;
+
+/* -------------------------------------
+ Comparison Expressions
+------------------------------------- */
+
+ComparisonExpr
+ : RangeExpr
+ | RangeExpr Comp {
+ tokenizer.State = ParseState.Default;
+ } RangeExpr
+ {
+ $$ = new ComparisonExpr ((ExprSingle) $1, (ExprSingle) $4, (ComparisonOperator) $2);
+ }
+ ;
+
+Comp // returns ComparisonOperator
+ : ValueComp
+ | GeneralComp
+ | NodeComp
+ ;
+
+ValueComp
+ : EQ
+ {
+ $$ = ComparisonOperator.ValueEQ;
+ }
+ | NE
+ {
+ $$ = ComparisonOperator.ValueNE;
+ }
+ | LT
+ {
+ $$ = ComparisonOperator.ValueLT;
+ }
+ | LE
+ {
+ $$ = ComparisonOperator.ValueLE;
+ }
+ | GT
+ {
+ $$ = ComparisonOperator.ValueGT;
+ }
+ | GE
+ {
+ $$ = ComparisonOperator.ValueGE;
+ }
+ ;
+
+GeneralComp
+ : EQUAL
+ {
+ $$ = ComparisonOperator.GeneralEQ;
+ }
+ | NOT_EQUAL
+ {
+ $$ = ComparisonOperator.GeneralNE;
+ }
+ | LESSER
+ {
+ $$ = ComparisonOperator.GeneralLT;
+ }
+ | LESSER_EQUAL
+ {
+ $$ = ComparisonOperator.GeneralLE;
+ }
+ | GREATER
+ {
+ $$ = ComparisonOperator.GeneralGT;
+ }
+ | GREATER_EQUAL
+ {
+ $$ = ComparisonOperator.GeneralGE;
+ }
+ ;
+
+NodeComp
+ : IS
+ {
+ $$ = ComparisonOperator.NodeIs;
+ }
+ | LESSER2
+ {
+ $$ = ComparisonOperator.NodeFWD;
+ }
+ | GREATER2
+ {
+ $$ = ComparisonOperator.NodeBWD;
+ }
+ ;
+
+RangeExpr
+ : AdditiveExpr
+ | AdditiveExpr TO {
+ tokenizer.State = ParseState.Default;
+ } AdditiveExpr
+ {
+ $$ = new RangeExpr ((ExprSingle) $1, (ExprSingle)$4);
+ }
+ ;
+
+/* -------------------------------------
+ Arithmetic Expressions
+------------------------------------- */
+
+AdditiveExpr
+ : MultiplicativeExpr
+ | MultiplicativeExpr PLUS {
+ tokenizer.State = ParseState.Default;
+ } AdditiveExpr
+ {
+ $$ = new ArithmeticOperationExpr ((ExprSingle) $1, (ExprSingle) $4, ArithmeticOperator.Add);
+ }
+ | MultiplicativeExpr MINUS {
+ tokenizer.State = ParseState.Default;
+ } AdditiveExpr
+ {
+ $$ = new ArithmeticOperationExpr ((ExprSingle) $1, (ExprSingle) $4, ArithmeticOperator.Sub);
+ }
+ ;
+
+MultiplicativeExpr
+ : UnaryExpr
+ | UnaryExpr ASTERISK {
+ tokenizer.State = ParseState.Default;
+ } MultiplicativeExpr
+ {
+ $$ = new ArithmeticOperationExpr ((ExprSingle) $1, (ExprSingle) $4, ArithmeticOperator.Mul);
+ }
+ | UnaryExpr DIV {
+ tokenizer.State = ParseState.Default;
+ } MultiplicativeExpr
+ {
+ $$ = new ArithmeticOperationExpr ((ExprSingle) $1, (ExprSingle) $4, ArithmeticOperator.Div);
+ }
+ | UnaryExpr IDIV {
+ tokenizer.State = ParseState.Default;
+ } MultiplicativeExpr
+ {
+ $$ = new ArithmeticOperationExpr ((ExprSingle) $1, (ExprSingle) $4, ArithmeticOperator.IDiv);
+ }
+ | UnaryExpr MOD {
+ tokenizer.State = ParseState.Default;
+ } MultiplicativeExpr
+ {
+ $$ = new ArithmeticOperationExpr ((ExprSingle) $1, (ExprSingle) $4, ArithmeticOperator.IMod);
+ }
+ ;
+
+UnaryExpr
+ : UnionExpr
+ | MINUS UnionExpr
+ {
+ $$ = new MinusExpr ((ExprSingle) $2);
+ }
+ | PLUS UnionExpr
+ {
+ $$ = $2;
+ }
+ ;
+
+UnionExpr
+ : IntersectExceptExpr
+ | IntersectExceptExpr UNION {
+ tokenizer.State = ParseState.Default;
+ } UnionExpr
+ {
+ $$ = new GroupExpr ((ExprSingle) $1, (ExprSingle) $4, AggregationType.Union);
+ }
+ | IntersectExceptExpr BAR {
+ tokenizer.State = ParseState.Default;
+ } UnionExpr
+ {
+ $$ = new GroupExpr ((ExprSingle) $1, (ExprSingle) $4, AggregationType.Union);
+ }
+ ;
+
+IntersectExceptExpr
+ : ValueExpr
+ | ValueExpr INTERSECT {
+ tokenizer.State = ParseState.Default;
+ } IntersectExceptExpr
+ {
+ $$ = new GroupExpr ((ExprSingle) $1, (ExprSingle) $4, AggregationType.Intersect);
+ }
+ | ValueExpr EXCEPT {
+ tokenizer.State = ParseState.Default;
+ } IntersectExceptExpr
+ {
+ $$ = new GroupExpr ((ExprSingle) $1, (ExprSingle) $4, AggregationType.Except);
+ }
+ ;
+
+ValueExpr
+ : ValidateExpr
+ | PathExpr
+ ;
+
+/* -----------------
+ Validation Expressions
+----------------- */
+
+// FIXME: Here state transition is not well-tracked.
+
+ValidateExpr // returns ValidateExpr
+ : VALIDATE OptionalValidationMode OPEN_CURLY {
+ tokenizer.State = ParseState.Default;
+ tokenizer.PushState (ParseState.Operator);
+ } Expr CloseCurly
+ {
+ $$ = new ValidateExpr ((XmlSchemaContentProcessing) $2, (ExprSequence) $6);
+ }
+ ;
+
+OptionalValidationMode // returns XmlSchemaContentProcessing
+ : // empty
+ {
+ $$ = XmlSchemaContentProcessing.Strict; // FIXME: confirm
+ }
+ | LAX
+ {
+ $$ = XmlSchemaContentProcessing.Lax;
+ }
+ | STRICT
+ {
+ $$ = XmlSchemaContentProcessing.Strict;
+ }
+ ;
+
+/* -----------------
+ Path Expressions
+----------------- */
+
+PathExpr // returns PathExpr
+ : Slash
+ {
+ $$ = new PathRootExpr ();
+ }
+ | Slash RelativePathExpr
+ {
+ $$ = new PathSlashExpr (new PathRootExpr (), (ExprSingle) $2);
+ }
+ | Slash2 RelativePathExpr
+ {
+ $$ = new PathSlash2Expr (new PathRootExpr (), (ExprSingle) $2);
+ }
+ | RelativePathExpr
+ ;
+
+RelativePathExpr // returns PathExpr
+ : StepExpr
+ | StepExpr Slash RelativePathExpr
+ {
+ $$ = new PathSlashExpr ((ExprSingle) $1, (ExprSingle) $3);
+ }
+ | StepExpr Slash2 RelativePathExpr
+ {
+ $$ = new PathSlash2Expr ((ExprSingle) $1, (ExprSingle) $3);
+ }
+ ;
+
+StepExpr // returns ExprSingle
+ : AxisStep
+ | FilterStep
+ ;
+
+AxisStep // returns PathExpr
+ : ForwardOrReverseStep
+ | AxisStep Predicate
+ {
+ $$ = new FilterStepExpr ((ExprSingle) $1, (ExprSequence) $2);
+ }
+ ;
+
+ForwardOrReverseStep // returns ExprSingle
+ : ForwardStep
+ | ReverseStep
+ ;
+
+Predicate
+ : OPEN_BRACKET Expr CLOSE_BRACKET {
+ tokenizer.State = ParseState.Operator;
+ }
+ {
+ $$ = $2;
+ }
+ ;
+
+FilterStep // returns ExprSingle
+ : PrimaryExpr
+ | FilterStep Predicate
+ {
+ $$ = new FilterStepExpr ((ExprSingle) $1, (ExprSequence) $2);
+ }
+ ;
+
+ForwardStep // returns AxisStepExpr
+ : ForwardAxis NodeTest
+ {
+ $$ = new AxisStepExpr ((XPathAxis) $1, (XPath2NodeTest) $2);
+ }
+ | AbbrevForwardStep
+ ;
+
+ReverseStep // returns AxisStepExpr
+ : ReverseAxis NodeTest
+ {
+ $$ = new AxisStepExpr ((XPathAxis) $1, (XPath2NodeTest) $2);
+ }
+ | AbbrevReverseStep
+ ;
+
+ForwardAxis // returns XPathAxis
+ : CHILD COLON2
+ {
+ $$ = XPathAxis.Child;
+ }
+ | DESCENDANT COLON2
+ {
+ $$ = XPathAxis.Descendant;
+ }
+ | ATTRIBUTE COLON2
+ {
+ $$ = XPathAxis.Attribute;
+ }
+ | SELF COLON2
+ {
+ $$ = XPathAxis.Self;
+ }
+ | DESCENDANT_OR_SELF COLON2
+ {
+ $$ = XPathAxis.DescendantOrSelf;
+ }
+ | FOLLOWING_SIBLING COLON2
+ {
+ $$ = XPathAxis.FollowingSibling;
+ }
+ | FOLLOWING COLON2
+ {
+ $$ = XPathAxis.Following;
+ }
+ ;
+
+ReverseAxis // returns XPathAxis
+ : PARENT COLON2
+ {
+ $$ = XPathAxis.Parent;
+ }
+ | ANCESTOR COLON2
+ {
+ $$ = XPathAxis.Ancestor;
+ }
+ | PRECEDING_SIBLING COLON2
+ {
+ $$ = XPathAxis.PrecedingSibling;
+ }
+ | PRECEDING COLON2
+ {
+ $$ = XPathAxis.Preceding;
+ }
+ | ANCESTOR_OR_SELF COLON2
+ {
+ $$ = XPathAxis.AncestorOrSelf;
+ }
+ ;
+
+// LAMESPEC: in the XQuery spec, it is "@? NodeTest", but NodeKindTest
+// should not appear after AT. (imagine @processing-instruction::(name)).
+AbbrevForwardStep // returns NodeTestExpr
+ : NodeTest
+ {
+ $$ = new AxisStepExpr (XPathAxis.Child, (XPath2NodeTest) $1);
+ }
+ | AT NameTest
+ {
+ $$ = new AxisStepExpr (XPathAxis.Attribute, new XPath2NodeTest ((XmlQualifiedName) $2));
+ }
+ ;
+
+AbbrevReverseStep // returns AxisStepExpr
+ : DOT2
+ {
+ $$ = new AxisStepExpr (XPathAxis.Parent, null);
+ }
+ ;
+
+NodeTest // returns NodeTest
+ : KindTest
+ {
+ $$ = new XPath2NodeTest ((KindTest) $1);
+ }
+ | NameTest
+ {
+ $$ = new XPath2NodeTest ((XmlQualifiedName) $1);
+ }
+ ;
+
+NameTest // returns XmlQualifiedName
+ : QName
+ | Wildcard {
+ tokenizer.State = ParseState.Operator;
+ }
+ ;
+
+Wildcard // returns XmlQualifiedName /*ws:explicit*/
+ : ASTERISK
+ {
+ $$ = new XmlQualifiedName ("*", "*");
+ }
+ | WILD_LOCALNAME
+ {
+ $$ = (XmlQualifiedName) $1;
+ }
+ | WILD_PREFIX
+ {
+ $$ = (XmlQualifiedName) $1;
+ }
+ ;
+
+AtomicType // returns XmlTypeCode
+ : QName
+ {
+ $$ = GetAtomicTypeCode ((XmlQualifiedName) $1);
+ }
+ ;
+
+ItemType // returns ItemType
+ : AtomicType {
+ tokenizer.State = ParseState.OccurenceIndicator;
+ }
+ {
+ $$ = new ItemType ((XmlTypeCode) $1);
+ }
+ | KindTest
+ | ITEM OPEN_PAREN CLOSE_PAREN {
+ tokenizer.State = ParseState.OccurenceIndicator;
+ }
+ {
+ $$ = new ItemType (XmlTypeCode.Item);
+ }
+ ;
+
+KindTest // returns KindTest
+ : DocumentTest
+ | ElementTest
+ | AttributeTest
+ | PITest
+ | CommentTest
+ | TextTest
+ | AnyKindTest
+ ;
+
+PITest
+ : PROCESSING_INSTRUCTION OPEN_PAREN {
+ // LAMESPEC: push state is described as Operator, but should
+ // be OccurenceIndicator (as any KindTest could be followed by
+ // '?' '+' or '*')
+ tokenizer.PushState (ParseState.OccurenceIndicator);
+ tokenizer.State = ParseState.KindTestForPI;
+ } PITestContent CLOSE_PAREN {
+ tokenizer.PopState ();
+ }
+ {
+ $$ = $4;
+ }
+ ;
+
+PITestContent // returns KindTest
+ : // empty
+ {
+ $$ = new KindTest (XmlTypeCode.ProcessingInstruction);
+ }
+ | NCName
+ {
+ $$ = new XmlPITest ((string) $1);
+ }
+ | STRING_LITERAL
+ {
+ $$ = new XmlPITest ((string) $1);
+ }
+ ;
+
+CommentTest
+ : COMMENT OPEN_PAREN {
+ tokenizer.PushState (ParseState.OccurenceIndicator);
+ tokenizer.State = ParseState.KindTest;
+ } CLOSE_PAREN {
+ tokenizer.PopState ();
+ }
+ {
+ $$ = new KindTest (XmlTypeCode.Comment);
+ }
+ ;
+
+TextTest
+ : TEXT OPEN_PAREN {
+ tokenizer.PushState (ParseState.OccurenceIndicator);
+ tokenizer.State = ParseState.KindTest;
+ } CLOSE_PAREN {
+ tokenizer.PopState ();
+ }
+ {
+ $$ = new KindTest (XmlTypeCode.Text);
+ }
+ ;
+
+AnyKindTest
+ : NODE OPEN_PAREN {
+ tokenizer.PushState (ParseState.OccurenceIndicator);
+ tokenizer.State = ParseState.KindTest;
+ } CLOSE_PAREN {
+ tokenizer.PopState ();
+ }
+ {
+ $$ = new KindTest (XmlTypeCode.Node);
+ }
+ ;
+
+DocumentTest // returns DocumentTest
+ : DOCUMENT_NODE OPEN_PAREN {
+ tokenizer.PushState (ParseState.OccurenceIndicator);
+ tokenizer.State = ParseState.KindTest;
+ } DocumentTestContent CLOSE_PAREN {
+ tokenizer.PopState ();
+ }
+ {
+ $$ = $4;
+ }
+ ;
+
+DocumentTestContent // returns DocumentTest
+ : // empty
+ {
+ $$ = new KindTest (XmlTypeCode.Document);
+ }
+ | ElementTest
+ {
+ $$ = new DocumentTest ((ElementTest) $1);
+ }
+ ;
+
+ElementTest // returns ElementTest
+ : ELEMENT OPEN_PAREN {
+ tokenizer.PushState (ParseState.OccurenceIndicator);
+ tokenizer.State = ParseState.KindTest;
+ } ElementTestContent CLOSE_PAREN {
+ tokenizer.PopState ();
+ }
+ {
+ $$ = $4;
+ }
+ ;
+
+ElementTestContent // returns ElementTest
+ : // empty
+ {
+ $$ = new KindTest (XmlTypeCode.Element);
+ }
+ | ElementNameOrWildcard
+ {
+ $$ = new ElementTest ((XmlQualifiedName) $1);
+ }
+ | ElementNameOrWildcard COMMA TypeName OptionalQuestion
+ {
+ $$ = new ElementTest ((XmlQualifiedName) $1, (XmlQualifiedName) $3, (bool) $4);
+ }
+ ;
+
+OptionalQuestion // returns bool
+ : // empty
+ {
+ $$ = false;
+ }
+ | QUESTION
+ {
+ $$ = true;
+ }
+ ;
+
+AttributeTest // returns AttributeTest
+ : ATTRIBUTE OPEN_PAREN {
+ tokenizer.PushState (ParseState.OccurenceIndicator);
+ tokenizer.State = ParseState.KindTest;
+ } AttributeTestContent CLOSE_PAREN {
+ tokenizer.PopState ();
+ }
+ {
+ $$ = $4;
+ }
+ ;
+
+AttributeTestContent // returns AttributeTest
+ : // empty
+ {
+ $$ = AttributeTest.AnyAttribute;
+ }
+ | AttributeNameOrWildcard
+ {
+ $$ = new AttributeTest ((XmlQualifiedName) $1);
+ }
+ | AttributeNameOrWildcard COMMA TypeNameOrWildcard
+ {
+ $$ = new AttributeTest ((XmlQualifiedName) $1, (XmlQualifiedName) $3);
+ }
+ ;
+
+ElementName
+ : QName
+ ;
+
+AttributeName
+ : QName
+ ;
+
+TypeName
+ : QName
+ ;
+
+ElementNameOrWildcard // returns XmlQualifiedName
+ : ElementName
+ | ASTERISK
+ {
+ $$ = new XmlQualifiedName ("*", "*");
+ }
+ ;
+
+AttributeNameOrWildcard // returns XmlQualifiedName
+ : AttributeName
+ | ASTERISK
+ {
+ $$ = new XmlQualifiedName ("*", "*");
+ }
+ ;
+
+TypeNameOrWildcard // returns XmlQualifiedName
+ : TypeName
+ | ASTERISK
+ {
+ $$ = new XmlQualifiedName ("*", "*");
+ }
+ ;
+
+/* ----------------
+ Primary Expressions
+---------------- */
+
+PrimaryExpr // returns ExprSingle
+ : Literal {
+ tokenizer.State = ParseState.Operator;
+ }
+ | VarRef
+ | ParenthesizedExpr
+ | ContextItemExpr
+ | FunctionCall
+ | Constructor
+ | OrderedExpr
+ | UnorderedExpr
+ ;
+
+Literal
+ : DECIMAL_LITERAL
+ {
+ $$ = new DecimalLiteralExpr ((decimal) $1);
+ }
+ | DOUBLE_LITERAL
+ {
+ $$ = new DoubleLiteralExpr ((double) $1);
+ }
+ | STRING_LITERAL
+ {
+ $$ = new StringLiteralExpr ((string) $1);
+ }
+ ;
+
+/*
+NUMERIC_LITERAL
+ : IntegerLiteral
+ | DecimalLiteral
+ | DoubleLiteral
+ ;
+
+IntegerLiteral
+ : Digits
+ ;
+
+DecimalLiteral
+ : DOT Digits
+ | Digits DOT OptDigits
+ ;
+
+DoubleLiteral
+ : DoubleDecimalPartSpec ExponentSpec
+ ;
+
+DoubleDecimalPartSpec
+ : DOT Digits
+ | Digits
+ | Digits DOT OptDigits
+
+ExponentSpec
+ : // empty/*
+ | ExponentAlpha Digits
+ | ExponentAlpha PLUS Digits
+ | ExponentAlpha MINUS Digits
+ ;
+
+ExponentAlpha
+ : LARGE_E
+ | SMALL_E
+ ;
+
+OptDigits
+ : // empty/*
+ | Digits
+ ;
+
+Digits
+ : ZERO_TO_NINE_SEQ
+ ;
+
+STRING_LITERAL
+ : QUOT STRING_LITERALContentQuot
+ | APOS STRING_LITERALContentApos
+ ;
+
+STRING_LITERALContentQuot
+ : PREDEFINED_ENTITY_REF
+ | CHAR_REF
+ | QUOT2
+ | REMAINING_LITERAL
+ ;
+
+STRING_LITERALContentApos
+ : PREDEFINED_ENTITY_REF
+ | CHAR_REF
+ | APOS2
+ | REMAINING_LITERAL
+ ;
+*/
+
+VarRef // returns VariableReferenceExpr
+ : DOLLAR {
+ tokenizer.State = ParseState.VarName;
+ } VarName
+ {
+ $$ = new VariableReferenceExpr ((XmlQualifiedName) $3);
+ }
+ ;
+
+VarName // returns XmlQualifiedName
+ : QName {
+ tokenizer.State = ParseState.Operator;
+ }
+ {
+ $$ = $1;
+ }
+ ;
+
+ParenthesizedExpr // returns ParenthesizedExpr
+ : OPEN_PAREN OptionalExpr CLOSE_PAREN {
+ tokenizer.State = ParseState.Operator;
+ }
+ {
+ $$ = new ParenthesizedExpr ((ExprSequence) $2);
+ }
+ ;
+
+OptionalExpr
+ : // empty
+ {
+ $$ = new ExprSequence ();
+ }
+ | Expr
+ ;
+
+ContextItemExpr // returns ContextItemExpr
+ : DOT {
+ tokenizer.State = ParseState.Operator;
+ }
+ {
+ $$ = new ContextItemExpr ();
+ }
+ ;
+
+FunctionCall
+ : QName OPEN_PAREN {
+ tokenizer.State = ParseState.Default;
+ } OptionalExpr CLOSE_PAREN {
+ tokenizer.State = ParseState.Operator;
+ }
+ {
+ XmlQualifiedName name = (XmlQualifiedName) $1;
+ if (name.Namespace == "")
+ name = new XmlQualifiedName (name.Name, tokenizer.DefaultFunctionNamespace);
+ if (name.Namespace != ""
+ && name.Namespace != InternalPool.XdtNamespace
+ && reservedFunctionNames [name.Name] != null)
+ throw new XmlQueryCompileException (String.Format ("'{0}' is reserved and cannot be used as a function name.", name.Name));
+
+ $$ = new FunctionCallExpr (name, (ExprSequence) $4);
+ }
+ ;
+
+OrderedExpr
+ : ORDERED OPEN_BRACKET Expr CLOSE_BRACKET
+ {
+ $$ = new OrderSpecifiedExpr ((ExprSequence) $3, true);
+ }
+ ;
+
+UnorderedExpr
+ : UNORDERED OPEN_BRACKET {
+ tokenizer.PushState (ParseState.Operator);
+ tokenizer.State = ParseState.Default;
+ } Expr CLOSE_BRACKET {
+ tokenizer.PopState ();
+ }
+ {
+ $$ = new OrderSpecifiedExpr ((ExprSequence) $4, false);
+ }
+ ;
+
+
+/* -----------------
+ Constructors
+----------------- */
+
+
+Constructor // returns ExprSingle
+ : DirElemConstructor
+ | ComputedConstructor
+ | XmlComment
+ | XmlPI
+ | XmlCData
+ ;
+
+DirElemConstructor // returns XmlElemConstructor
+ : LESSER {
+ if (tokenizer.State == ParseState.ElementContent)
+ tokenizer.PushState (tokenizer.State);
+// if (tokenizer.State == ParseState.Default)
+ else // considering <foo></foo><bar></bar> there after </foo> state is Operator.
+ tokenizer.PushState (ParseState.Operator);
+ tokenizer.State = ParseState.StartTag;
+ // FIXME: tokenizer.Space = WhitespaceHandling.Significant;
+ } QName AttributeList FollowDirElemConstructor {
+ tokenizer.PopState ();
+ }
+ {
+ ExprSequence expr = new ExprSequence ();
+ expr.AddRange ((ICollection) $4);
+ expr.AddRange ((ICollection) $5);
+ $$ = new XmlElemConstructor ((XmlQualifiedName) $3, expr);
+ }
+ ;
+
+FollowDirElemConstructor // returns ExprSequence
+ : EMPTY_TAG_CLOSE
+ {
+ $$ = new ExprSequence ();
+ }
+ | GREATER {
+ tokenizer.State = ParseState.ElementContent;
+ } ElementContentList END_TAG_START {
+ tokenizer.State = ParseState.EndTag;
+ } QName {
+// tokenizer.Space = WhitespaceHandling.Arbitrary;
+ } GREATER
+ {
+ $$ = $3;
+ }
+ ;
+
+ElementContentList // returns ExprSequence
+ : // empty
+ {
+ $$ = new ExprSequence ();
+ }
+ | ElementContent ElementContentList
+ {
+ ExprSequence el = (ExprSequence) $2;
+ el.Insert (0, (ExprSingle) $1);
+ $$ = el;
+ }
+ ;
+
+AttributeList // returns XmlAttrConstructorList
+ : // empty
+ {
+ $$ = new XmlAttrConstructorList ();
+ }
+ | /* space */ Attribute AttributeList
+ {
+ XmlAttrConstructorList al = (XmlAttrConstructorList) $2;
+ al.Insert (0, (XmlAttrConstructor) $1);
+ $$ = al;
+ }
+ ;
+
+Attribute // returns XmlAttrConstructor
+ : QName /* opt-space */ EQUAL /* opt-space */ AttributeValue
+ {
+ $$ = new XmlAttrConstructor ((XmlQualifiedName) $1, (ExprSequence) $3);
+ }
+ ;
+
+/*
+// FIXME: it should be more complex
+AttributeValue // returns ExprSequence
+ : STRING_LITERAL
+ {
+ ExprSequence es = new ExprSequence ();
+ es.Insert (0, new StringLiteralExpr ((string) $1));
+ $$ = es;
+ }
+ ;
+*/
+
+AttributeValue // returns ExprSequence
+ : QUOT {
+ tokenizer.State = ParseState.QuotAttributeContent;
+ } AttributeValueContentSequence QUOT {
+ tokenizer.State = ParseState.StartTag;
+ }
+ {
+ $$ = $3;
+ }
+ | APOS {
+ tokenizer.State = ParseState.AposAttributeContent;
+ } AttributeValueContentSequence APOS {
+ tokenizer.State = ParseState.StartTag;
+ }
+ {
+ $$ = $3;
+ }
+ ;
+
+
+AttributeValueContentSequence // returns ExprSequence
+ : // empty
+ {
+ $$ = new ExprSequence ();
+ }
+ | AttributeValueContent AttributeValueContentSequence
+ {
+ ExprSequence es = (ExprSequence) $2;
+ es.Insert (0, (ExprSingle) $1);
+ $$ = es;
+ }
+ ;
+
+AttributeValueContent // returns ExprSingle
+ : ATT_VALUE_LITERAL // including "{{", "}}" and char/predefined entities
+ {
+ $$ = new StringLiteralExpr ((string) $1);
+ }
+ | EnclosedExpr
+ ;
+
+EnclosedExpr // returns EnclosedExpr
+ // FIXME: check if this state transition is valid for ElementContent and AttributeValueContent
+ : OPEN_CURLY {
+ switch (tokenizer.State) {
+ case ParseState.ElementContent:
+ case ParseState.QuotAttributeContent:
+ case ParseState.AposAttributeContent:
+ tokenizer.PushState (tokenizer.State);
+ break;
+ }
+ tokenizer.State = ParseState.Default;
+ } Expr CloseCurly
+ {
+ $$ = new EnclosedExpr ((ExprSequence) $3);
+ }
+ ;
+
+ElementContent // returns ExprSingle
+ : ELEM_CONTENT_LITERAL // including "{{", "}}" and char/predefined entities
+ {
+ $$ = new XmlTextConstructor ((string) $1);
+ }
+ | DirElemConstructor
+ | EnclosedExpr
+ | XmlCData
+ | XmlComment
+ | XmlPI
+ ;
+
+XmlCData
+ : XML_CDATA_START XML_CDATA_TO_END
+ {
+ $$ = new XmlTextConstructor ((string) $2);
+ }
+ ;
+
+XmlComment // returns XmlCommentConstructor
+ : XML_COMMENT_START XML_COMMENT_TO_END
+ {
+ $$ = new XmlCommentConstructor ((string) $2);
+ }
+ ;
+
+XmlPI // returns XmlPIConstructor
+ : XML_PI_START {
+ tokenizer.PushState (tokenizer.State);
+ tokenizer.State = ParseState.XmlPI;
+ } PITarget {
+ tokenizer.State = ParseState.XmlPIContent;
+ } XML_PI_TO_END {
+ tokenizer.PopState ();
+ }
+ {
+ string name = (string) $3;
+ $$ = new XmlPIConstructor (name, (string) $5);
+ }
+ ;
+
+PITarget
+ : NCName
+ ;
+
+ComputedConstructor // returns ExprSingle
+ : CompElemConstructor
+ | CompAttrConstructor
+ | CompDocConstructor
+ | CompTextConstructor
+ | CompXmlPI
+ | CompXmlComment
+ | CompNSConstructor
+ ;
+
+CompElemConstructor
+ : ELEMENT QName OPEN_CURLY Expr CloseCurly
+ {
+ $$ = new XmlElemConstructor ((XmlQualifiedName) $2, (ExprSequence) $4);
+ }
+ | ELEMENT OPEN_CURLY Expr CloseCurly OPEN_CURLY Expr CloseCurly
+ {
+ $$ = new XmlElemConstructor ((ExprSequence) $3, (ExprSequence) $6);
+ }
+ ;
+
+CompAttrConstructor
+ : ATTRIBUTE QName OPEN_CURLY Expr CloseCurly
+ {
+ $$ = new XmlAttrConstructor ((XmlQualifiedName) $2, (ExprSequence) $4);
+ }
+ | ATTRIBUTE OPEN_CURLY Expr CloseCurly OPEN_CURLY Expr CloseCurly
+ {
+ $$ = new XmlAttrConstructor ((ExprSequence) $3, (ExprSequence) $6);
+ }
+ ;
+
+CompNSConstructor
+ : NAMESPACE NCName OPEN_CURLY Expr CloseCurly
+ {
+ $$ = new XmlNSConstructor ((string) $2, (ExprSequence) $4);
+ }
+ ;
+
+CompDocConstructor
+ : DOCUMENT OPEN_CURLY Expr CloseCurly
+ {
+ $$ = new XmlDocConstructor ((ExprSequence) $3);
+ }
+ ;
+
+CompTextConstructor
+ : TEXT OPEN_CURLY Expr CloseCurly
+ {
+ $$ = new XmlTextConstructor ((ExprSequence) $3);
+ }
+ ;
+
+CompXmlComment
+ : COMMENT OPEN_CURLY Expr CloseCurly
+ {
+ $$ = new XmlCommentConstructor ((ExprSequence) $3);
+ }
+ ;
+
+CompXmlPI
+ : PROCESSING_INSTRUCTION NCName OPEN_CURLY Expr CloseCurly
+ {
+ $$ = new XmlPIConstructor ((string) $2, (ExprSequence) $4);
+ }
+ | PROCESSING_INSTRUCTION OPEN_CURLY Expr CloseCurly OPEN_CURLY Expr CloseCurly
+ {
+ $$ = new XmlPIConstructor ((ExprSequence) $3, (ExprSequence) $6);
+ }
+ ;
+
+/* -----------------
+ Terminal Wrappers
+----------------- */
+
+
+NCName // returns string
+ : NCNAME
+ ;
+
+QName // returns XmlQualifiedName. Note that this state is just a wrapper for state transition.
+ : QNAME {
+ switch (tokenizer.State) {
+ case ParseState.Default:
+ tokenizer.State = ParseState.Operator;
+ break;
+ case ParseState.ItemType:
+ tokenizer.State = ParseState.OccurenceIndicator;
+ break;
+ case ParseState.KindTest:
+ case ParseState.SchemaContextStep:
+ tokenizer.State = ParseState.CloseKindTest;
+ break;
+ case ParseState.ExtKey:
+ tokenizer.State = ParseState.ExprComment;
+ break;
+ }
+ }
+ ;
+
+Slash
+ : SLASH {
+ switch (tokenizer.State) {
+ case ParseState.Operator:
+ tokenizer.State = ParseState.Default;
+ break;
+ case ParseState.KindTest:
+ tokenizer.State = ParseState.SchemaContextStep;
+ break;
+ }
+ }
+ ;
+
+Slash2
+ : SLASH2 {
+ if (tokenizer.State == ParseState.Operator)
+ tokenizer.State = ParseState.Default;
+ }
+ ;
+
+CloseCurly
+ : CLOSE_CURLY {
+ if (tokenizer.State == ParseState.Operator)
+ tokenizer.PopState ();
+ }
+ ;
+
+%%
+
+}
+
+#endif
diff --git a/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XQueryStaticContext.cs b/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XQueryStaticContext.cs
new file mode 100755
index 00000000000..e17033f21a9
--- /dev/null
+++ b/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XQueryStaticContext.cs
@@ -0,0 +1,231 @@
+//
+// XQueryStaticContext.cs - XQuery static context components
+//
+// Author:
+// Atsushi Enomoto <atsushi@ximian.com>
+//
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+#if NET_2_0
+
+using System;
+using System.Collections;
+using System.Collections.Specialized;
+using System.Globalization;
+using System.IO;
+using System.Security.Policy;
+using System.Xml;
+using System.Xml.Query;
+using System.Xml.Schema;
+using Mono.Xml.XPath2;
+
+namespace Mono.Xml.XPath2
+{
+ // Holds static context, that is created for each module.
+ internal class XQueryStaticContext
+ {
+ public static XQueryStaticContext Optimize (XQueryStaticContext ctx)
+ {
+ // FIXME: do type promotion and expression reduction
+ return ctx;
+ }
+
+ // Don't keep XQueryCompileOptions and XQueryMainModule
+ // inside this class. I don't want them affect this instance
+ // by being modified externally after the compilation.
+
+ public XQueryStaticContext (
+ XQueryCompileOptions options,
+ XQueryCompileContext compileContext,
+ ExprSequence queryBody,
+ XmlSchemaSet inScopeSchemas,
+ IDictionary inScopeVariables,
+ XQueryFunctionTable functionSignatures,
+ IXmlNamespaceResolver nsResolver,
+ string defaultFunctionNamespace,
+ bool preserveWhitespace,
+ bool constructionSpace,
+ bool defaultOrdered,
+ string baseUri,
+ Evidence evidence,
+ XQueryCommandImpl commandImpl)
+ {
+ // Initialization phase.
+ compat = options.Compatibility;
+ nameTable = options.NameTable;
+ this.queryBody = queryBody;
+ this.nsResolver = nsResolver;
+ this.defaultFunctionNamespace = defaultFunctionNamespace;
+// elemNSManager = new XmlNamespaceManager (nameTable);
+// funcNSManager = new XmlNamespaceManager (nameTable);
+ xqueryFlagger = options.XQueryFlagger;
+ xqueryStaticFlagger = options.XQueryStaticFlagger;
+// xqueryResolver = options.KnownDocumentResolver;
+ knownCollections = (IDictionary) options.KnownCollections.Clone ();
+ functions = functionSignatures;
+ this.compileContext = compileContext;
+ this.inScopeSchemas = inScopeSchemas;
+ this.inScopeVariables = inScopeVariables;
+ this.preserveWhitespace = preserveWhitespace;
+ this.preserveConstructionSpace = constructionSpace;
+ this.defaultOrdered = defaultOrdered;
+ this.baseUri = baseUri;
+ this.defaultCollation = options.DefaultCollation;
+ // FIXME: set contextItemStaticType
+ // FIXME: set extDocResolver
+
+ this.evidence = evidence;
+ this.commandImpl = commandImpl;
+ }
+
+ // It holds in-effect components et. al.
+ XQueryCompileContext compileContext;
+
+ XmlNameTable nameTable;
+ Evidence evidence; // for safe custom function execution / safe assembly loading
+ XQueryCommandImpl commandImpl; // for event delegate
+
+ ExprSequence queryBody;
+
+ // See XQuery 1.0, 2.1.1 "Static Context"
+ XmlQueryDialect compat; // XPath 1.0 compatibility mode
+ IXmlNamespaceResolver nsResolver; // Manages "statically known namespaces" and "default element/type namespace"
+ string defaultFunctionNamespace; // default function namespace
+ XmlSchemaSet inScopeSchemas; // in-scope schemas
+ IDictionary inScopeVariables;
+ Type contextItemStaticType; // TODO: context item static type?
+ XQueryFunctionTable functions;
+
+ // Statically known collations is not defined here. It is equal to all supported CultureInfo.
+// IDictionary staticallyKnownCollations;
+
+ CultureInfo defaultCollation; // or TextInfo ?
+ bool preserveConstructionSpace; // construction mode
+ bool defaultOrdered; // Ordering mode
+ bool preserveWhitespace; // Xml space policy
+ string baseUri;
+// XmlResolver extDocResolver; // statically known documents
+ IDictionary knownCollections; // statically known collections
+ bool xqueryFlagger;
+ bool xqueryStaticFlagger;
+
+ // Properties
+
+ public XQueryCompileContext CompileContext {
+ get { return compileContext; }
+ }
+
+ public XmlQueryDialect Compatibility {
+ get { return compat; }
+ }
+
+ public ExprSequence QueryBody {
+ get { return queryBody; }
+ }
+
+ public XmlNameTable NameTable {
+ get { return nameTable; }
+ }
+
+ public Evidence Evidence {
+ get { return evidence; }
+ }
+
+ public CultureInfo DefaultCollation {
+ get { return defaultCollation; }
+ }
+
+ public XmlSchemaSet InScopeSchemas {
+ get { return inScopeSchemas; }
+ }
+
+ // in-scope functions.
+ public XQueryFunctionTable InScopeFunctions {
+ get { return functions; }
+ }
+
+ // in-scope variables. XmlQualifiedName to XPathItem
+ public IDictionary InScopeVariables {
+ get { return inScopeVariables; }
+ }
+
+ public bool PreserveWhitespace {
+ get { return preserveWhitespace; }
+ }
+
+ public bool PreserveConstructionSpace {
+ get { return preserveConstructionSpace; }
+ }
+
+ public bool DefaultOrdered {
+ get { return defaultOrdered; }
+ }
+
+ // statically known collections. string to ICollection (or XPathItemIterator, or XPathNodeIterator).
+ public IDictionary KnownCollections {
+ get { return knownCollections; }
+ }
+
+ public bool XQueryFlagger {
+ get { return xqueryFlagger; }
+ }
+
+ public bool XQueryStaticFlagger {
+ get { return xqueryStaticFlagger; }
+ }
+
+ public string BaseUri {
+ get { return baseUri; }
+ }
+
+ public IXmlNamespaceResolver NSResolver {
+ get { return nsResolver; }
+ }
+
+ public string DefaultFunctionNamespace {
+ get { return defaultFunctionNamespace; }
+ set { defaultFunctionNamespace = value; }
+ }
+
+ // FIXME: consider those from imported modules
+ public XQueryFunction ResolveFunction (XmlQualifiedName name)
+ {
+ XQueryFunction f = functions [name];
+ if (f != null)
+ return f;
+ return null;
+ }
+
+ // FIXME: wait for W3C clarification.
+ internal CultureInfo GetCulture (string collation)
+ {
+ return null;
+ }
+
+ internal void OnMessageEvent (object sender, QueryEventArgs e)
+ {
+ commandImpl.ProcessMessageEvent (sender, e);
+ }
+ }
+}
+#endif
diff --git a/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XQueryTokenizer.cs b/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XQueryTokenizer.cs
new file mode 100755
index 00000000000..67a10da8ce9
--- /dev/null
+++ b/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XQueryTokenizer.cs
@@ -0,0 +1,1285 @@
+//
+// XQueryTokenizer.cs
+//
+// Author:
+// Atsushi Enomoto <atsushi@ximian.com>
+//
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+#if NET_2_0
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System.Security.Policy;
+using System.Xml;
+using System.Xml.Query;
+using System.Xml.Schema;
+using System.Xml.XPath;
+using Mono.Xml.XQuery;
+using Mono.Xml.XPath2;
+using Mono.Xml;
+
+namespace Mono.Xml.XQuery.Parser
+{
+ // FIXME: make internal in the future
+ public class XQueryTokenizer
+ : Mono.Xml.XQuery.Parser.yyParser.yyInput, IXmlLineInfo
+ {
+ int line = 1;
+ int column = 0;
+ bool nextIncrementLine;
+
+ // namespace resolver
+ XmlNamespaceManager nsResolver;
+ string defaultFunctionNamespace = XQueryFunction.Namespace;
+
+ // input source
+ TextReader source;
+ int peekChar = -1;
+
+ // token info
+ int currentToken;
+ string prefixName;
+ object tokenValue;
+
+ int lookAheadToken = -1;
+ object lookAheadTokenValue;
+
+ // state info
+ WhitespaceHandling ws = WhitespaceHandling.Arbitrary;
+ ParseState state = ParseState.Default;
+ Stack stateStack;
+
+ char [] buffer = new char [30];
+ int bufferIndex;
+
+ public XQueryTokenizer (TextReader reader)
+ {
+ this.source = reader;
+
+ stateStack = new Stack ();
+
+ nsResolver = new XmlNamespaceManager (new NameTable ());
+ nsResolver.AddNamespace ("xs", XmlSchema.Namespace);
+ nsResolver.AddNamespace ("xdt", InternalPool.XdtNamespace);
+ // FIXME: Are they really predefined?
+ nsResolver.AddNamespace ("xsi", XmlSchema.InstanceNamespace);
+ nsResolver.AddNamespace ("fn", "http://www.w3.org/2003/11/xpath-functions");
+ nsResolver.AddNamespace ("local", "http://www.w3.org/2003/11/xquery-local-functions");
+ }
+
+ internal IXmlNamespaceResolver NSResolver {
+ get { return nsResolver; }
+ }
+
+ internal string DefaultFunctionNamespace {
+ get { return defaultFunctionNamespace; }
+ set { defaultFunctionNamespace = value; }
+ }
+
+ public void AddNamespace (string prefix, string ns)
+ {
+ nsResolver.AddNamespace (prefix, ns);
+ }
+
+ public bool advance ()
+ {
+ if (currentToken < 0)
+ return false;
+ if (lookAheadToken >= 0) {
+ tokenValue = lookAheadTokenValue;
+ currentToken = lookAheadToken;
+ lookAheadToken = -1;
+ }
+ else
+ currentToken = ParseToken ();
+ return currentToken >= 0;
+ }
+
+ public int token ()
+ {
+ return currentToken;
+ }
+
+ public object value ()
+ {
+ return tokenValue;
+ }
+
+ public bool HasLineInfo ()
+ {
+ return true;
+ }
+
+ public int LineNumber {
+ get { return line; }
+ }
+
+ public int LinePosition {
+ get { return column; }
+ }
+
+ internal WhitespaceHandling Space {
+ get { return ws; }
+ set { ws = value; }
+ }
+
+ internal ParseState State {
+ get { return state; }
+ set {
+// Console.Error.WriteLine ("**** eno **** state transition from {0} to {1}, stack count = {2}", state, value, stateStack.Count);
+//foreach (ParseState ps in stateStack.ToArray ()) Console.Error.WriteLine ("***** eno ***** " + ps);
+ state = value;
+ }
+ }
+
+ internal void PushState (ParseState newState)
+ {
+ stateStack.Push (newState);
+// Console.Error.WriteLine ("**** eno **** state pushed {0}, added stack count = {1}", newState, stateStack.Count);
+//foreach (ParseState ps in stateStack.ToArray ()) Console.Error.WriteLine ("***** eno ***** " + ps);
+ }
+
+ internal void PopState ()
+ {
+ if (stateStack.Count == 0)
+ throw Error ("Internal state transition error. State stack is empty.");
+ state = (ParseState) stateStack.Pop ();
+// Console.Error.WriteLine ("**** eno **** state pop, now as {0}, stack count = {1}", state, stateStack.Count);
+//foreach (ParseState ps in stateStack.ToArray ()) Console.Error.WriteLine ("***** eno ***** " + ps);
+ }
+
+ private XmlQueryCompileException Error (string message)
+ {
+ return new XmlQueryCompileException (message, this, null, null);
+ }
+
+ private int ParseToken ()
+ {
+ bufferIndex = 0;
+
+ switch (state) {
+ case ParseState.StartTag:
+ break;
+ default:
+ SkipWhitespaces ();
+ break;
+ }
+ /*
+ switch (ws) {
+ case WhitespaceHandling.Arbitrary:
+ SkipWhitespaces ();
+ break;
+ case WhitespaceHandling.Explicit:
+ if (!XmlChar.IsWhitespace (PeekChar ()))
+ throw Error ("Whitespace is required.");
+ goto case WhitespaceHandling.Arbitrary;
+ }
+ */
+
+ int c = PeekChar ();
+ if (c < 0)
+ return -1;
+
+ // FIXME: consider DOUBLE_LITERAL
+ if (Char.IsNumber ((char) c)) {
+ tokenValue = ReadDecimal (false);
+ return Token.DECIMAL_LITERAL;
+ }
+
+ switch (state) {
+ case ParseState.OccurenceIndicator:
+ return ParseOccurenceIndicator ();
+ case ParseState.XmlPIContent:
+ return ParseXmlPIContent ();
+ case ParseState.XmlComment:
+ return ParseXmlCommentContent ();
+ case ParseState.ElementContent:
+ return ParseElementContent ();
+ case ParseState.StartTag:
+ return ParseStartTag ();
+ case ParseState.QuotAttributeContent:
+ return ParseAttributeContent ('"');
+ case ParseState.AposAttributeContent:
+ return ParseAttributeContent ('\'');
+ default:
+ return ParseDefault ();
+ }
+ }
+
+ private int ParseXQueryComment ()
+ {
+ while (true) {
+ int c = ReadChar ();
+ if (c < 0)
+ throw Error ("Unexpected end of query text inside XML processing instruction content");
+ if (c == ':') {
+ if (PeekChar () == ')') {
+ ReadChar ();
+ tokenValue = CreateValueString ();
+ return Token.XML_PI_TO_END;
+ }
+ else
+ AddValueChar (':');
+ }
+ else
+ AddValueChar ((char) c);
+ }
+ }
+
+ private int ParseXmlPIContent ()
+ {
+ while (true) {
+ int c = ReadChar ();
+ if (c < 0)
+ throw Error ("Unexpected end of query text inside XML processing instruction content");
+ if (c == '?') {
+ if (PeekChar () == '>') {
+ ReadChar ();
+ tokenValue = CreateValueString ();
+ return Token.XML_PI_TO_END;
+ }
+ else
+ AddValueChar ('?');
+ }
+ else
+ AddValueChar ((char) c);
+ }
+ }
+
+ private int ParseXmlCommentContent ()
+ {
+ // FIXME: handle ---> correctly
+ while (true) {
+ int c = ReadChar ();
+ if (c < 0)
+ throw Error ("Unexpected end of query text inside XML comment content");
+ if (c == '-') {
+ if (PeekChar () == '-') {
+ ReadChar ();
+ if (PeekChar () == '>') {
+ tokenValue = CreateValueString ();
+ return Token.XML_COMMENT_TO_END;
+ } else {
+ AddValueChar ('-');
+ AddValueChar ('-');
+ }
+ }
+ else
+ AddValueChar ('-');
+ }
+ else
+ AddValueChar ((char) c);
+ }
+ }
+
+ private int ParseXmlCDataContent ()
+ {
+ // FIXME: handle ]]]> correctly
+ while (true) {
+ int c = ReadChar ();
+ if (c < 0)
+ throw Error ("Unexpected end of query text inside XML CDATA section content");
+ if (c == ']') {
+ ReadChar ();
+ if (PeekChar () == ']') {
+ ReadChar ();
+ if (PeekChar () == '>') {
+ tokenValue = CreateValueString ();
+ return Token.XML_CDATA_TO_END;
+ } else {
+ AddValueChar (']');
+ AddValueChar (']');
+ }
+ }
+ else
+ AddValueChar (']');
+ }
+ else
+ AddValueChar ((char) c);
+ }
+ }
+
+ private int ParseElementContent ()
+ {
+ tokenValue = null;
+ int c = PeekChar ();
+ if (c < 0)
+ throw Error ("Unexpected end of query text inside XML processing instruction content");
+ switch ((char) c) {
+ case '<':
+ case '{':
+ return ParseDefault ();
+ }
+
+ while (true) {
+ c = PeekChar ();
+ if (c < 0)
+ throw Error ("Unexpected end of query text inside XML processing instruction content");
+ switch ((char) c) {
+ case '&':
+ ReadChar ();
+ ReadPredefinedEntity ();
+ continue;
+ case '<':
+ tokenValue += CreateValueString ();
+ return Token.ELEM_CONTENT_LITERAL;
+ default:
+ AddValueChar ((char) c);
+ ReadChar ();
+ continue;
+ }
+ }
+ }
+
+ private void ReadPredefinedEntity ()
+ {
+ string token = ReadOneToken ();
+ Expect (";");
+ switch (token) {
+ case "lt":
+ AddValueChar ('<');
+ return;
+ case "gt":
+ AddValueChar ('>');
+ return;
+ case "amp":
+ AddValueChar ('&');
+ return;
+ case "quot":
+ AddValueChar ('"');
+ return;
+ case "apos":
+ AddValueChar ('\'');
+ return;
+ default:
+ throw Error (String.Format ("Unexpected general entity name: {0} .", token));
+ }
+ }
+
+ // FIXME: not used as yet
+ private int ParseExtContent ()
+ {
+ // FIXME: handle :::) correctly
+ while (true) {
+ int c = PeekChar ();
+ if (c < 0)
+ throw Error ("Unexpected end of query text inside external content");
+ if (c == ':') {
+ ReadChar ();
+ if (PeekChar () == ':') {
+ ReadChar ();
+ if (PeekChar () == ')') {
+ tokenValue = CreateValueString ();
+ return Token.EXT_CONTENT;
+ } else {
+ AddValueChar (':');
+ AddValueChar (':');
+ }
+ }
+ else
+ AddValueChar (':');
+ }
+ else
+ AddValueChar ((char) c);
+ }
+ }
+
+ private int ParseOccurenceIndicator ()
+ {
+ state = ParseState.Operator;
+ switch (PeekChar ()) {
+ case '?':
+ ReadChar ();
+ return Token.QUESTION;
+ case '*':
+ ReadChar ();
+ return Token.ASTERISK;
+ case '+':
+ ReadChar ();
+ return Token.PLUS;
+ default:
+ return ParseOperator ();
+ }
+ }
+
+ private int ParseStartTag ()
+ {
+ int c = PeekChar ();
+ switch (c) {
+ case '\'':
+ ReadChar ();
+ return Token.APOS;
+ case '"':
+ ReadChar ();
+ return Token.QUOT;
+ case '>':
+ ReadChar ();
+ return Token.GREATER;
+ case '/':
+ ReadChar ();
+ Expect (">");
+ return Token.EMPTY_TAG_CLOSE;
+ }
+ // FIXME: there seems a bug in the spec that StartTag
+ // state must accept QName without heading space for
+ // start tag name.
+// if (!XmlChar.IsWhitespace (PeekChar ()))
+// throw Error ("Whitespace is required.");
+ SkipWhitespaces ();
+ return ParseDefault (); // only QName is allowed here.
+ }
+
+ private int ParseAttributeContent (char closeChar)
+ {
+ int t = Token.ATT_VALUE_LITERAL;
+ while (true) {
+ int c = PeekChar ();
+ if (c < 0)
+ throw Error ("Unexpected end of attribute value content.");
+ if (c == closeChar) {
+ ReadChar ();
+ c = PeekChar ();
+ if (c == closeChar) {
+ ReadChar ();
+ AddValueChar (closeChar);
+ }
+ else
+ t = closeChar == '"' ? Token.QUOT : Token.APOS;
+ }
+ else if (c == '{') {
+ ReadChar ();
+ c = PeekChar ();
+ if (c == '{') {
+ ReadChar ();
+ AddValueChar ('{');
+ }
+ else
+ t = Token.OPEN_CURLY;
+ }
+ else
+ AddValueChar ((char) ReadChar ());
+
+ if (t != Token.ATT_VALUE_LITERAL) {
+ if (bufferIndex > 0) {
+ lookAheadToken = t;
+ tokenValue = CreateValueString ();
+ return Token.ATT_VALUE_LITERAL;
+ }
+ else
+ return t;
+ }
+ }
+ }
+
+ private int ParseOperator ()
+ {
+ // TODO: implement
+ return ParseDefault ();
+ }
+
+ private int ParseDefault ()
+ {
+ int c = ReadChar ();
+ switch (c) {
+ case '.':
+ if (PeekChar () == '.') {
+ ReadChar ();
+ return Token.DOT2;
+ }
+ else if (Char.IsNumber ((char) PeekChar ())) {
+ tokenValue = ReadDecimal (true);
+ }
+ return Token.DOT;
+ case ',':
+ return Token.COMMA;
+ case ';':
+ return Token.SEMICOLON;
+ case '(':
+ if (PeekChar () == ':') {
+ ReadChar ();
+ if (PeekChar () == ':') {
+ ReadChar ();
+ return Token.PRAGMA_OPEN;
+ }
+ ParseXQueryComment ();
+ return ParseToken (); // start again
+ }
+ return Token.OPEN_PAREN;
+ case ')':
+ return Token.CLOSE_PAREN;
+ case ':':
+ switch (PeekChar ()) {
+ case ':':
+ ReadChar ();
+ if (PeekChar () == ')') {
+ ReadChar ();
+ return Token.PRAGMA_CLOSE;
+ }
+ return Token.COLON2;
+ case ')':
+ ReadChar ();
+ return Token.CLOSE_PAREN_COLON;
+ case '=':
+ ReadChar ();
+ return Token.COLON_EQUAL;
+ }
+ return Token.COLON;
+ case '[':
+ return Token.OPEN_BRACKET;
+ case ']':
+ return Token.CLOSE_BRACKET;
+ case '{':
+ return Token.OPEN_CURLY;
+ case '}':
+ return Token.CLOSE_CURLY;
+ case '$':
+ return Token.DOLLAR;
+ case '\'':
+ tokenValue = ReadQuoted ('\'');
+ return Token.STRING_LITERAL;
+ case '"':
+ tokenValue = ReadQuoted ('"');
+ return Token.STRING_LITERAL;
+ case '=':
+ return Token.EQUAL;
+ case '<':
+ // only happens when state is ElementContent
+ // (otherwise it might be "/foo</bar")
+ if (state == ParseState.ElementContent) {
+ switch ((char) PeekChar ()) {
+ case '/':
+ ReadChar ();
+ return Token.END_TAG_START;
+ case '!':
+ ReadChar ();
+ switch (PeekChar ()) {
+ case '-':
+ ReadChar ();
+ if (ReadChar () != '-')
+ throw Error ("Invalid sequence of characters '<!-'.");
+
+ return Token.XML_COMMENT_START;
+ case '[':
+ ReadChar ();
+ Expect ("CDATA[");
+ return Token.XML_CDATA_START;
+ }
+ throw Error ("Invalid sequence of characters '<!'.");
+ case '?':
+ ReadChar ();
+ return Token.XML_PI_START;
+ default:
+ return Token.LESSER;
+ }
+ }
+
+ switch (PeekChar ()) {
+ case '<':
+ ReadChar ();
+ return Token.LESSER2;
+ case '=':
+ ReadChar ();
+ return Token.LESSER_EQUAL;
+ }
+ return Token.LESSER;
+ case '>':
+ switch (PeekChar ()) {
+ case '>':
+ ReadChar ();
+ return Token.GREATER2;
+ case '=':
+ ReadChar ();
+ return Token.GREATER_EQUAL;
+ }
+ return Token.GREATER;
+ case '|':
+ return Token.BAR;
+ case '*':
+ if (PeekChar () == ':') {
+ ReadChar ();
+ // FIXME: more check
+ tokenValue = new XmlQualifiedName (ReadOneToken (), "*");
+ return Token.WILD_PREFIX;
+ }
+ return Token.ASTERISK;
+ case '+':
+ return Token.PLUS;
+ case '-':
+ return Token.MINUS;
+ case '/':
+ // only happens when state is StartTag
+ // (otherwise it might be "/>$extvar")
+ if (state == ParseState.StartTag && PeekChar () == '>') {
+ ReadChar ();
+ return Token.EMPTY_TAG_CLOSE;
+ }
+ if (PeekChar () == '/') {
+ ReadChar ();
+ return Token.SLASH2;
+ }
+ return Token.SLASH;
+ case '?':
+ return Token.QUESTION;
+ case '@':
+ return Token.AT;
+ }
+
+ peekChar = c;
+ prefixName = null;
+ string name = ReadOneToken ();
+
+ tokenValue = name;
+ bool validKeyword = false;
+
+ switch (state) {
+ case ParseState.XmlSpaceDecl:
+ switch (name) {
+ case "preserve":
+ return Token.PRESERVE;
+ case "strip":
+ return Token.STRIP;
+ }
+ break;
+ case ParseState.CloseKindTest:
+ if (name == "nillable")
+ return Token.NILLABLE;
+ break;
+ case ParseState.ExtKey:
+ switch (name) {
+ case "pragma":
+ return Token.PRAGMA;
+ case "extension":
+ return Token.EXTENSION;
+ }
+ break;
+ case ParseState.KindTest:
+ switch (name) {
+ case "context":
+ return Token.CONTEXT;
+ case "element":
+ return Token.ELEMENT;
+ case "global":
+ return Token.GLOBAL;
+ case "type":
+ return Token.TYPE;
+ }
+ break;
+ case ParseState.ItemType:
+ switch (name) {
+ case "attribute":
+ return Token.ATTRIBUTE;
+ case "comment":
+ return Token.COMMENT;
+ case "document-node":
+ return Token.DOCUMENT_NODE;
+ case "element":
+ return Token.ELEMENT;
+ case "empty":
+ return Token.EMPTY;
+ case "item":
+ return Token.ITEM;
+ case "node":
+ return Token.NODE;
+ case "processing-instruction":
+ return Token.PROCESSING_INSTRUCTION;
+ case "text":
+ return Token.TEXT;
+ }
+ break;
+ case ParseState.NamespaceKeyword:
+ switch (name) {
+ case "declare":
+ return Token.DECLARE;
+ case "default":
+ return Token.DEFAULT;
+ case "element":
+ return Token.ELEMENT;
+ case "function":
+ return Token.FUNCTION;
+ case "namespace":
+ return Token.NAMESPACE;
+ }
+ break;
+ case ParseState.OccurenceIndicator:
+ case ParseState.Operator:
+ switch (name) {
+ case "and":
+ case "as":
+ case "ascending":
+ case "at":
+ case "base-uri":
+ case "by":
+ case "case":
+ case "cast":
+ case "castable":
+ case "collation":
+ case "declare":
+ case "default":
+ case "descending":
+ case "div":
+ case "element":
+ case "else":
+ case "empty":
+ case "eq":
+ case "every":
+ case "except":
+ case "external":
+ case "for":
+ case "function":
+ case "ge":
+ case "global":
+ case "greatest":
+ case "gt":
+ case "idiv":
+ case "import":
+ case "in":
+ case "instance":
+ case "intersect":
+ case "is":
+ case "lax":
+ case "le":
+ case "least":
+ case "let":
+ case "lt":
+ case "mod":
+ case "module":
+ case "namespace":
+ case "ne":
+ case "of":
+ case "or":
+ case "order":
+ case "ordered":
+ case "ordering":
+ case "return":
+ case "satisfies":
+ case "schema":
+ case "skip":
+ case "some":
+ case "stable":
+ case "strict":
+ case "then":
+ case "to":
+ case "treat":
+ case "typwswitch":
+ case "union":
+ case "unordered":
+ case "variable":
+ case "where":
+ case "xmlspace":
+ validKeyword = true;
+ break;
+ }
+ break;
+ case ParseState.Default:
+ switch (name) {
+ case "ancestor":
+ case "ancestor-or-self":
+ case "as":
+ case "attribute":
+ case "base-uri":
+ case "child":
+ case "collation":
+ case "comment":
+ case "construction":
+ case "declare":
+ case "default":
+ case "descendant":
+ case "descendant-or-self":
+ case "document":
+ case "document-node":
+ case "element":
+ case "every":
+ case "following":
+ case "following-sibling":
+ case "for":
+ case "function":
+ case "global":
+ case "if":
+ case "import":
+ case "lax":
+ case "let":
+ case "module":
+ case "namespace":
+ case "node":
+ case "ordered":
+ case "parent":
+ case "preceding":
+ case "preceding-sibling":
+ case "processing-instruction":
+ case "schema":
+ case "self":
+ case "some":
+ case "strict":
+ case "strip":
+ case "text":
+ case "typeswitch":
+ case "unordered":
+ case "validate":
+ case "validation":
+ case "version":
+ case "xmlspace":
+ case "xquery":
+ validKeyword = true;
+ break;
+ }
+ break;
+ }
+
+ if (validKeyword) {
+ switch (name) {
+ case "xquery":
+ return Token.XQUERY;
+ case "version":
+ return Token.VERSION;
+ case "pragma":
+ return Token.PRAGMA;
+ case "extension":
+ return Token.EXTENSION;
+ case "module":
+ return Token.MODULE;
+ case "namespace":
+ return Token.NAMESPACE;
+ case "declare":
+ return Token.DECLARE;
+ case "xmlspace":
+ return Token.XMLSPACE;
+ case "preserve":
+ return Token.PRESERVE;
+ case "strip":
+ return Token.STRIP;
+ case "default":
+ return Token.DEFAULT;
+ case "construction":
+ return Token.CONSTRUCTION;
+ case "ordering":
+ return Token.ORDERING;
+ case "ordered":
+ return Token.ORDERED;
+ case "unordered":
+ return Token.UNORDERED;
+ case "document-node":
+ return Token.DOCUMENT_NODE;
+ case "document":
+ return Token.DOCUMENT;
+ case "element":
+ return Token.ELEMENT;
+ case "attribute":
+ return Token.ATTRIBUTE;
+ case "processing-instruction":
+ return Token.PROCESSING_INSTRUCTION;
+ case "comment":
+ return Token.COMMENT;
+ case "text":
+ return Token.TEXT;
+ case "node":
+ return Token.NODE;
+ case "function":
+ return Token.FUNCTION;
+ case "collation":
+ return Token.COLLATION;
+ case "base-uri":
+ return Token.BASEURI;
+ case "import":
+ return Token.IMPORT;
+ case "schema":
+ return Token.SCHEMA;
+ case "at":
+ return Token.AT;
+ case "variable":
+ return Token.VARIABLE;
+ case "as":
+ return Token.AS;
+ case "external":
+ return Token.EXTERNAL;
+ case "validation":
+ return Token.VALIDATION;
+ case "lax":
+ return Token.LAX;
+ case "strict":
+ return Token.STRICT;
+ case "skip":
+ return Token.SKIP;
+ case "return":
+ return Token.RETURN;
+ case "for":
+ return Token.FOR;
+ case "let":
+ return Token.LET;
+ case "in":
+ return Token.IN;
+ case "where":
+ return Token.WHERE;
+ case "order":
+ return Token.ORDER;
+ case "by":
+ return Token.BY;
+ case "stable":
+ return Token.STABLE;
+ case "ascending":
+ return Token.ASCENDING;
+ case "descending":
+ return Token.DESCENDING;
+ case "empty":
+ return Token.EMPTY;
+ case "greatest":
+ return Token.GREATEST;
+ case "least":
+ return Token.LEAST;
+ case "some":
+ return Token.SOME;
+ case "every":
+ return Token.EVERY;
+ case "satisfies":
+ return Token.SATISFIES;
+ case "is":
+ return Token.IS;
+ case "to":
+ return Token.TO;
+ case "eq":
+ return Token.EQ;
+ case "ne":
+ return Token.NE;
+ case "lt":
+ return Token.LT;
+ case "le":
+ return Token.LE;
+ case "gt":
+ return Token.GT;
+ case "ge":
+ return Token.GE;
+ case "and":
+ return Token.AND;
+ case "or":
+ return Token.OR;
+ case "instance":
+ return Token.INSTANCE;
+ case "of":
+ return Token.OF;
+ case "if":
+ return Token.IF;
+ case "then":
+ return Token.THEN;
+ case "else":
+ return Token.ELSE;
+ case "typeswitch":
+ return Token.TYPESWITCH;
+ case "case":
+ return Token.CASE;
+ case "treat":
+ return Token.TREAT;
+ case "castable":
+ return Token.CASTABLE;
+ case "cast":
+ return Token.CAST;
+ case "div":
+ return Token.DIV;
+ case "idiv":
+ return Token.IDIV;
+ case "mod":
+ return Token.MOD;
+ case "union":
+ return Token.UNION;
+ case "intersect":
+ return Token.INTERSECT;
+ case "except":
+ return Token.EXCEPT;
+ case "validate":
+ return Token.VALIDATE;
+ case "context":
+ return Token.CONTEXT;
+ case "nillable":
+ return Token.NILLABLE;
+ case "item":
+ return Token.ITEM;
+ case "global":
+ return Token.GLOBAL;
+ case "type":
+ return Token.TYPE;
+ case "child":
+ return Token.CHILD;
+ case "descendant":
+ return Token.DESCENDANT;
+ case "self":
+ return Token.SELF;
+ case "descendant-or-self":
+ return Token.DESCENDANT_OR_SELF;
+ case "following-sibling":
+ return Token.FOLLOWING_SIBLING;
+ case "following":
+ return Token.FOLLOWING;
+ case "parent":
+ return Token.PARENT;
+ case "ancestor":
+ return Token.ANCESTOR;
+ case "preceding":
+ return Token.PRECEDING;
+ case "preceding-sibling":
+ return Token.PRECEDING_SIBLING;
+ case "ancestor-or-self":
+ return Token.ANCESTOR_OR_SELF;
+ }
+ }
+
+ switch (state) {
+ case ParseState.NamespaceDecl:
+ case ParseState.NamespaceKeyword:
+ case ParseState.XmlSpaceDecl:
+ case ParseState.KindTestForPI:
+ case ParseState.XmlPI:
+ return Token.NCNAME;
+ }
+
+ if (PeekChar () == ':') {
+ ReadChar ();
+ prefixName = name;
+ switch (PeekChar ()) {
+ case '*':
+ ReadChar ();
+ name = "*";
+ break;
+ case '=': // ex. let foo:= ...
+ ReadChar ();
+ tokenValue = new XmlQualifiedName (name, nsResolver.DefaultNamespace);
+ lookAheadToken = Token.COLON_EQUAL;
+ return Token.QNAME;
+ default:
+ name = ReadOneToken ();
+ break;
+ }
+
+ string ns = nsResolver.LookupNamespace (prefixName);
+ if (ns == null)
+ throw Error (String.Format ("Prefix '{0}' is not mapped to any namespace URI.", prefixName));
+ tokenValue = new XmlQualifiedName (name, ns);
+ prefixName = null;
+ return name == "*" ? Token.WILD_LOCALNAME : Token.QNAME;
+ }
+ tokenValue = new XmlQualifiedName (name);
+ return Token.QNAME;
+ }
+
+ private int PeekChar ()
+ {
+ if (peekChar == -1)
+ peekChar = source.Read ();
+ return peekChar;
+ }
+
+ private int ReadChar ()
+ {
+ int ret;
+ if (peekChar != -1) {
+ ret = peekChar;
+ peekChar = -1;
+ }
+ else
+ ret = source.Read ();
+
+ if (nextIncrementLine) {
+ line++;
+ column = 0;
+ nextIncrementLine = false;
+ }
+ column++;
+ switch (ret) {
+ case '\r':
+ break;
+ case '\n':
+ nextIncrementLine = true;
+ goto default;
+ default:
+ break;
+ }
+
+ return ret;
+ }
+
+ private void SkipWhitespaces ()
+ {
+ while (true) {
+ switch (PeekChar ()) {
+ case ' ':
+ case '\t':
+ case '\r':
+ case '\n':
+ ReadChar ();
+ continue;
+ default:
+ return;
+ }
+ }
+ }
+
+ private void AddValueChar (char c)
+ {
+ if (bufferIndex == buffer.Length) {
+ char [] newBuf = new char [bufferIndex * 2];
+ Array.Copy (buffer, newBuf, bufferIndex);
+ buffer = newBuf;
+ }
+ buffer [bufferIndex++] = c;
+ }
+
+ private string CreateValueString ()
+ {
+ return new string (buffer, 0, bufferIndex);
+ }
+
+ private void Expect (string expected)
+ {
+ for (int i = 0; i < expected.Length; i++)
+ if (ReadChar () != expected [i])
+ throw Error (String.Format ("Expected token '{0}' did not appear.", expected));
+ }
+
+ // TODO: parse three quoted
+ private string ReadQuoted (char quoteChar)
+ {
+ bufferIndex = 0;
+ bool loop = true;
+ do {
+ int c = ReadChar ();
+ switch (c) {
+ case -1:
+ case '"':
+ if (quoteChar == '"')
+ loop = false;
+ break;
+ case '\'':
+ if (quoteChar == '\'')
+ loop = false;
+ break;
+ default:
+ AddValueChar ((char) c);
+ break;
+ }
+ } while (loop);
+
+ return CreateValueString ();
+ }
+
+ private decimal ReadDecimal (bool floatingPoint)
+ {
+ bufferIndex = 0;
+ bool cond = true;
+ do {
+ int c = PeekChar ();
+ if (c < 0) {
+ cond = false;
+ }
+ // FIXME: more complex
+ else if (Char.IsNumber ((char) c) || c == '.') {
+ ReadChar ();
+ AddValueChar ((char) c);
+ continue;
+ }
+ else
+ cond = false;
+ } while (cond);
+ string s = (floatingPoint ? "." : "") + CreateValueString ();
+ return decimal.Parse (s);
+ }
+
+ private string ReadOneToken ()
+ {
+ bufferIndex = 0;
+ bool loop = true;
+ do {
+ int c = PeekChar ();
+ switch (c) {
+ case -1:
+ case ' ':
+ case '\t':
+ case '\r':
+ case '\n':
+ loop = false;
+ break;
+ default:
+ if (!IsTokenContinuable (c)) {
+ if (c == ':') {
+ if (prefixName != null)
+ throw new XmlQueryCompileException ("Invalid colon was found.");
+ prefixName = CreateValueString ();
+ }
+ loop = false;
+ break;
+ }
+
+ ReadChar ();
+ AddValueChar ((char) c);
+ break;
+ }
+ } while (loop);
+
+ return CreateValueString ();
+ }
+
+ private bool IsTokenContinuable (int c)
+ {
+ switch (c) {
+ case '-':
+ case '_':
+ case '.':
+ return true;
+ }
+ return XmlChar.IsNCNameChar (c);
+ }
+
+ }
+
+ public enum WhitespaceHandling {
+ Arbitrary,
+ Explicit,
+ Significant
+ }
+
+ public enum ParseState {
+ Default,
+ Operator,
+ NamespaceDecl,
+ NamespaceKeyword,
+ XmlSpaceDecl,
+ ItemType,
+ KindTest,
+ KindTestForPI,
+ CloseKindTest,
+ OccurenceIndicator,
+ SchemaContextStep,
+ VarName,
+ StartTag,
+ ElementContent,
+ EndTag,
+ XmlComment,
+ ExprComment,
+ ExtKey,
+ XmlPI,
+ XmlPIContent,
+ CDataSection,
+ QuotAttributeContent,
+ AposAttributeContent,
+ }
+
+}
+#endif
diff --git a/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XmlQueryCompileException.cs b/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XmlQueryCompileException.cs
new file mode 100755
index 00000000000..c0edeb22b80
--- /dev/null
+++ b/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XmlQueryCompileException.cs
@@ -0,0 +1,74 @@
+//
+// System.Xml.Query.XmlQueryCompileException
+//
+// Author:
+// Tim Coleman (tim@timcoleman.com)
+// Atsushi Enomoto (atsushi@ximian.com)
+//
+// Copyright (C) Tim Coleman, 2003
+// Copyright (C) Novell Inc., 2004
+//
+
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+#if NET_2_0
+
+using System;
+using System.Runtime.Serialization;
+
+namespace System.Xml.Query
+{
+ [Serializable]
+ public class XmlQueryCompileException : XmlQueryException
+ {
+ #region Constructors
+
+ protected XmlQueryCompileException (SerializationInfo info, StreamingContext context)
+ : base (info, context)
+ {
+ }
+
+ public XmlQueryCompileException ()
+ : base ("An XML Query Compile Exception has occurred.")
+ {
+ }
+
+ public XmlQueryCompileException (string res)
+ : this (res, null, null, null)
+ {
+ }
+
+ public XmlQueryCompileException (string resource, Exception exception)
+ : this (resource, null, null, exception)
+ {
+ }
+
+ internal XmlQueryCompileException (string message, IXmlLineInfo li, string sourceUri, Exception innerException)
+ : base (message, li, sourceUri, innerException)
+ {
+ }
+
+ #endregion // Constructors
+ }
+}
+
+#endif // NET_2_0
diff --git a/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XmlQueryException.cs b/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XmlQueryException.cs
new file mode 100755
index 00000000000..00e967cc32d
--- /dev/null
+++ b/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/XmlQueryException.cs
@@ -0,0 +1,112 @@
+//
+// System.Xml.Query.XmlQueryException
+//
+// Author:
+// Tim Coleman (tim@timcoleman.com)
+//
+// Copyright (C) Tim Coleman, 2003
+//
+
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+#if NET_2_0
+
+using System;
+using System.Runtime.Serialization;
+
+namespace System.Xml.Query
+{
+ [Serializable]
+ public class XmlQueryException : SystemException
+ {
+ #region Constructors
+
+ [MonoTODO]
+ protected XmlQueryException (SerializationInfo info, StreamingContext context)
+ : base (info, context)
+ {
+ throw new NotImplementedException ();
+ }
+
+ public XmlQueryException ()
+ : base ("An XML Query Exception has occurred.")
+ {
+ }
+
+ public XmlQueryException (string res)
+ : this (res, null, null, null)
+ {
+ }
+
+ public XmlQueryException (string resource, Exception exception)
+ : this (resource, null, null, exception)
+ {
+ }
+
+ internal XmlQueryException (string message, IXmlLineInfo lineInfo, string sourceUri, Exception innerException)
+ : base (BuildMessage (message, lineInfo, sourceUri), innerException)
+ {
+ }
+
+ static string BuildMessage (string message, IXmlLineInfo li, string sourceUri)
+ {
+ if (li != null && li.HasLineInfo ()) {
+ message = String.Format ("{0}. Location: {1} ({2}, {3}).", message, sourceUri, li.LineNumber, li.LinePosition);
+ }
+ else if (sourceUri != null)
+ message = String.Format ("{0}. Location: {1}", message, sourceUri);
+ return message;
+ }
+
+ #endregion // Constructors
+
+ #region Properties
+
+ [MonoTODO]
+ public int LineNumber {
+ get { throw new NotImplementedException (); }
+ }
+
+ [MonoTODO]
+ public int LinePosition {
+ get { throw new NotImplementedException (); }
+ }
+
+ [MonoTODO]
+ public string SourceUri {
+ get { throw new NotImplementedException(); }
+ }
+
+ #endregion // Properties
+
+ #region Methods
+
+ [MonoTODO]
+ public override void GetObjectData (SerializationInfo info, StreamingContext context)
+ {
+ throw new NotImplementedException();
+ }
+ #endregion // Methods
+ }
+}
+
+#endif // NET_2_0
diff --git a/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/skeleton-2.0.cs b/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/skeleton-2.0.cs
new file mode 100755
index 00000000000..e6bc3b1b856
--- /dev/null
+++ b/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath2/skeleton-2.0.cs
@@ -0,0 +1,364 @@
+# jay skeleton
+
+# character in column 1 determines outcome...
+# # is a comment
+# . is copied
+# t is copied as //t if -t is set
+# other lines are interpreted to call jay procedures
+
+.// created by jay 0.7 (c) 1998 Axel.Schreiner@informatik.uni-osnabrueck.de
+.
+.#if NET_2_0
+.
+ prolog ## %{ ... %} prior to the first %%
+
+.
+. /** error output stream.
+. It should be changeable.
+. */
+. internal System.IO.TextWriter ErrorOutput = System.Console.Out;
+.
+. /** simplified error message.
+. @see <a href="#yyerror(java.lang.String, java.lang.String[])">yyerror</a>
+. */
+. internal void yyerror (string message) {
+. yyerror(message, null);
+. }
+.
+. /** (syntax) error message.
+. Can be overwritten to control message format.
+. @param message text to be displayed.
+. @param expected vector of acceptable tokens, if available.
+. */
+. internal void yyerror (string message, string[] expected) {
+. if ((expected != null) && (expected.Length > 0)) {
+. ErrorOutput.Write (message+", expecting");
+. for (int n = 0; n < expected.Length; ++ n)
+. ErrorOutput.Write (" "+expected[n]);
+. ErrorOutput.WriteLine ();
+. } else
+. ErrorOutput.WriteLine (message);
+. }
+.
+. /** debugging support, requires the package jay.yydebug.
+. Set to null to suppress debugging messages.
+. */
+t internal yydebug.yyDebug debug;
+.
+ debug ## tables for debugging support
+.
+. /** index-checked interface to yyNames[].
+. @param token single character or %token value.
+. @return token name or [illegal] or [unknown].
+. */
+t internal static string yyname (int token) {
+t if ((token < 0) || (token > yyNames.Length)) return "[illegal]";
+t string name;
+t if ((name = yyNames[token]) != null) return name;
+t return "[unknown]";
+t }
+.
+. /** computes list of expected tokens on error by tracing the tables.
+. @param state for which to compute the list.
+. @return list of token names.
+. */
+. internal string[] yyExpecting (int state) {
+. int token, n, len = 0;
+. bool[] ok = new bool[yyNames.Length];
+.
+. if ((n = yySindex[state]) != 0)
+. for (token = n < 0 ? -n : 0;
+. (token < yyNames.Length) && (n+token < yyTable.Length); ++ token)
+. if (yyCheck[n+token] == token && !ok[token] && yyNames[token] != null) {
+. ++ len;
+. ok[token] = true;
+. }
+. if ((n = yyRindex[state]) != 0)
+. for (token = n < 0 ? -n : 0;
+. (token < yyNames.Length) && (n+token < yyTable.Length); ++ token)
+. if (yyCheck[n+token] == token && !ok[token] && yyNames[token] != null) {
+. ++ len;
+. ok[token] = true;
+. }
+.
+. string [] result = new string[len];
+. for (n = token = 0; n < len; ++ token)
+. if (ok[token]) result[n++] = yyNames[token];
+. return result;
+. }
+.
+. /** the generated parser, with debugging messages.
+. Maintains a state and a value stack, currently with fixed maximum size.
+. @param yyLex scanner.
+. @param yydebug debug message writer implementing yyDebug, or null.
+. @return result of the last reduction, if any.
+. @throws yyException on irrecoverable parse error.
+. */
+. internal Object yyparse (yyParser.yyInput yyLex, Object yyd)
+. {
+t this.debug = (yydebug.yyDebug)yyd;
+. return yyparse(yyLex);
+. }
+.
+. /** initial size and increment of the state/value stack [default 256].
+. This is not final so that it can be overwritten outside of invocations
+. of yyparse().
+. */
+. internal int yyMax;
+.
+. /** executed at the beginning of a reduce action.
+. Used as $$ = yyDefault($1), prior to the user-specified action, if any.
+. Can be overwritten to provide deep copy, etc.
+. @param first value for $1, or null.
+. @return first.
+. */
+. internal Object yyDefault (Object first) {
+. return first;
+. }
+.
+. /** the generated parser.
+. Maintains a state and a value stack, currently with fixed maximum size.
+. @param yyLex scanner.
+. @return result of the last reduction, if any.
+. @throws yyException on irrecoverable parse error.
+. */
+. internal Object yyparse (yyParser.yyInput yyLex)
+. {
+. if (yyMax <= 0) yyMax = 256; // initial size
+. int yyState = 0; // state stack ptr
+. int [] yyStates = new int[yyMax]; // state stack
+. Object yyVal = null; // value stack ptr
+. Object [] yyVals = new Object[yyMax]; // value stack
+. int yyToken = -1; // current input
+. int yyErrorFlag = 0; // #tks to shift
+.
+ local ## %{ ... %} after the first %%
+
+. int yyTop = 0;
+. goto skip;
+. yyLoop:
+. yyTop++;
+. skip:
+. for (;; ++ yyTop) {
+. if (yyTop >= yyStates.Length) { // dynamically increase
+. int[] i = new int[yyStates.Length+yyMax];
+. yyStates.CopyTo (i, 0);
+. yyStates = i;
+. Object[] o = new Object[yyVals.Length+yyMax];
+. yyVals.CopyTo (o, 0);
+. yyVals = o;
+. }
+. yyStates[yyTop] = yyState;
+. yyVals[yyTop] = yyVal;
+t if (debug != null) debug.push(yyState, yyVal);
+.
+. yyDiscarded: for (;;) { // discarding a token does not change stack
+. int yyN;
+. if ((yyN = yyDefRed[yyState]) == 0) { // else [default] reduce (yyN)
+. if (yyToken < 0) {
+. yyToken = yyLex.advance() ? yyLex.token() : 0;
+
+t if (debug != null)
+t debug.lex(yyState, yyToken, yyname(yyToken), yyLex.value());
+. }
+. if ((yyN = yySindex[yyState]) != 0 && ((yyN += yyToken) >= 0)
+. && (yyN < yyTable.Length) && (yyCheck[yyN] == yyToken)) {
+t if (debug != null)
+t debug.shift(yyState, yyTable[yyN], yyErrorFlag-1);
+. yyState = yyTable[yyN]; // shift to yyN
+. yyVal = yyLex.value();
+. yyToken = -1;
+. if (yyErrorFlag > 0) -- yyErrorFlag;
+. goto yyLoop;
+. }
+. if ((yyN = yyRindex[yyState]) != 0 && (yyN += yyToken) >= 0
+. && yyN < yyTable.Length && yyCheck[yyN] == yyToken)
+. yyN = yyTable[yyN]; // reduce (yyN)
+. else
+. switch (yyErrorFlag) {
+.
+. case 0:
+. yyerror(String.Format ("syntax error, got token `{0}'", yyname (yyToken)), yyExpecting(yyState));
+t if (debug != null) debug.error("syntax error");
+. goto case 1;
+. case 1: case 2:
+. yyErrorFlag = 3;
+. do {
+. if ((yyN = yySindex[yyStates[yyTop]]) != 0
+. && (yyN += Token.yyErrorCode) >= 0 && yyN < yyTable.Length
+. && yyCheck[yyN] == Token.yyErrorCode) {
+t if (debug != null)
+t debug.shift(yyStates[yyTop], yyTable[yyN], 3);
+. yyState = yyTable[yyN];
+. yyVal = yyLex.value();
+. goto yyLoop;
+. }
+t if (debug != null) debug.pop(yyStates[yyTop]);
+. } while (-- yyTop >= 0);
+t if (debug != null) debug.reject();
+. throw new yyParser.yyException("irrecoverable syntax error");
+.
+. case 3:
+. if (yyToken == 0) {
+t if (debug != null) debug.reject();
+. throw new yyParser.yyException("irrecoverable syntax error at end-of-file");
+. }
+t if (debug != null)
+t debug.discard(yyState, yyToken, yyname(yyToken),
+t yyLex.value());
+. yyToken = -1;
+. goto yyDiscarded; // leave stack alone
+. }
+. }
+. int yyV = yyTop + 1-yyLen[yyN];
+t if (debug != null)
+t debug.reduce(yyState, yyStates[yyV-1], yyN, yyRule[yyN], yyLen[yyN]);
+. yyVal = yyDefault(yyV > yyTop ? null : yyVals[yyV]);
+. switch (yyN) {
+
+ actions ## code from the actions within the grammar
+
+. }
+. yyTop -= yyLen[yyN];
+. yyState = yyStates[yyTop];
+. int yyM = yyLhs[yyN];
+. if (yyState == 0 && yyM == 0) {
+t if (debug != null) debug.shift(0, yyFinal);
+. yyState = yyFinal;
+. if (yyToken < 0) {
+. yyToken = yyLex.advance() ? yyLex.token() : 0;
+
+t if (debug != null)
+t debug.lex(yyState, yyToken,yyname(yyToken), yyLex.value());
+. }
+. if (yyToken == 0) {
+t if (debug != null) debug.accept(yyVal);
+. return yyVal;
+. }
+. goto yyLoop;
+. }
+. if (((yyN = yyGindex[yyM]) != 0) && ((yyN += yyState) >= 0)
+. && (yyN < yyTable.Length) && (yyCheck[yyN] == yyState))
+. yyState = yyTable[yyN];
+. else
+. yyState = yyDgoto[yyM];
+t if (debug != null) debug.shift(yyStates[yyTop], yyState);
+. goto yyLoop;
+. }
+. }
+. }
+.
+ tables ## tables for rules, default reduction, and action calls
+.
+ epilog ## text following second %%
+.namespace yydebug {
+. using System;
+. internal interface yyDebug {
+. void push (int state, Object value);
+. void lex (int state, int token, string name, Object value);
+. void shift (int from, int to, int errorFlag);
+. void pop (int state);
+. void discard (int state, int token, string name, Object value);
+. void reduce (int from, int to, int rule, string text, int len);
+. void shift (int from, int to);
+. void accept (Object value);
+. void error (string message);
+. void reject ();
+. }
+.
+. class yyDebugSimple : yyDebug {
+. void println (string s){
+. Console.Error.WriteLine (s);
+. }
+.
+. public void push (int state, Object value) {
+. println ("push\tstate "+state+"\tvalue "+value);
+. }
+.
+. public void lex (int state, int token, string name, Object value) {
+. println("lex\tstate "+state+"\treading "+name+"\tvalue "+value);
+. }
+.
+. public void shift (int from, int to, int errorFlag) {
+. switch (errorFlag) {
+. default: // normally
+. println("shift\tfrom state "+from+" to "+to);
+. break;
+. case 0: case 1: case 2: // in error recovery
+. println("shift\tfrom state "+from+" to "+to
+. +"\t"+errorFlag+" left to recover");
+. break;
+. case 3: // normally
+. println("shift\tfrom state "+from+" to "+to+"\ton error");
+. break;
+. }
+. }
+.
+. public void pop (int state) {
+. println("pop\tstate "+state+"\ton error");
+. }
+.
+. public void discard (int state, int token, string name, Object value) {
+. println("discard\tstate "+state+"\ttoken "+name+"\tvalue "+value);
+. }
+.
+. public void reduce (int from, int to, int rule, string text, int len) {
+. println("reduce\tstate "+from+"\tuncover "+to
+. +"\trule ("+rule+") "+text);
+. }
+.
+. public void shift (int from, int to) {
+. println("goto\tfrom state "+from+" to "+to);
+. }
+.
+. public void accept (Object value) {
+. println("accept\tvalue "+value);
+. }
+.
+. public void error (string message) {
+. println("error\t"+message);
+. }
+.
+. public void reject () {
+. println("reject");
+. }
+.
+. }
+.}
+.// %token constants
+. class Token {
+ tokens public const int
+. }
+. namespace yyParser {
+. using System;
+. /** thrown for irrecoverable syntax errors and stack overflow.
+. */
+. internal class yyException : System.Exception {
+. public yyException (string message) : base (message) {
+. }
+. }
+.
+. /** must be implemented by a scanner object to supply input to the parser.
+. */
+. internal interface yyInput {
+. /** move on to next token.
+. @return false if positioned beyond tokens.
+. @throws IOException on input error.
+. */
+. bool advance (); // throws java.io.IOException;
+. /** classifies current token.
+. Should not be called if advance() returned false.
+. @return current %token or single character.
+. */
+. int token ();
+. /** associated with current token.
+. Should not be called if advance() returned false.
+. @return value for token().
+. */
+. Object value ();
+. }
+. }
+.} // close outermost namespace, that MUST HAVE BEEN opened in the prolog
+.
+.#endif
+