소스 검색

2003-11-24 Atsushi Enomoto <[email protected]>

	* Parser.jay, Expression.cs, Iterator.cs :
	  Added ExprParens and ParensIterator classes which is used to handle
	  precedence of parenthesized expressions.
	  (e.g. consider "(preceding::*)[3]" and "preceding::[3]" )

	* Expression.cs, Iterator.cs :
	  Added RequireSorting property for each Expr and BaseIterator classes.
	  SlashIterator.MoveNext() now considers correct sorting. But
	  considering performance, it separates two logics, sorted and sortless
	  depending on RequireSorting of left iterator and right expression.

	* Iterator.cs :
	  SimpleIterator.ctor() should consider when nav is null.
	  FollowingIterator.MoveNext() and PrecedingIterator.MoveNext() should
	  not return any nodes.
	  AncestorIterator and AncestorOrSelfIterator copy ctr() should clone
	  positions.
	  AncestorIterator.MoveNext() should skip Root if context node is
	  Root itself.
	  FollowingIterator.MoveNext() should not handle children of context
	  itself.
	  PrecedingIterator.MoveNext() should skip its ancestors.
	  AxisIterator.ReverseAxis should be dependent on its containing iter.
	  UnionIterator.MoveNext() should consider comparison of nodes in
	  different document. The behavior is implementation dependent.
	  (see XSLT spec 12.1)

svn path=/trunk/mcs/; revision=20389
Atsushi Eno 22 년 전
부모
커밋
d0a53d86bb

+ 29 - 0
mcs/class/System.XML/System.Xml.XPath/ChangeLog

@@ -1,3 +1,32 @@
+2003-11-24  Atsushi Enomoto  <[email protected]>
+
+	* Parser.jay, Expression.cs, Iterator.cs :
+	  Added ExprParens and ParensIterator classes which is used to handle
+	  precedence of parenthesized expressions.
+	  (e.g. consider "(preceding::*)[3]" and "preceding::[3]" )
+
+	* Expression.cs, Iterator.cs :
+	  Added RequireSorting property for each Expr and BaseIterator classes.
+	  SlashIterator.MoveNext() now considers correct sorting. But
+	  considering performance, it separates two logics, sorted and sortless
+	  depending on RequireSorting of left iterator and right expression.
+
+	* Iterator.cs :
+	  SimpleIterator.ctor() should consider when nav is null.
+	  FollowingIterator.MoveNext() and PrecedingIterator.MoveNext() should
+	  not return any nodes.
+	  AncestorIterator and AncestorOrSelfIterator copy ctr() should clone
+	  positions.
+	  AncestorIterator.MoveNext() should skip Root if context node is
+	  Root itself.
+	  FollowingIterator.MoveNext() should not handle children of context
+	  itself.
+	  PrecedingIterator.MoveNext() should skip its ancestors.
+	  AxisIterator.ReverseAxis should be dependent on its containing iter.
+	  UnionIterator.MoveNext() should consider comparison of nodes in 
+	  different document. The behavior is implementation dependent.
+	  (see XSLT spec 12.1)
+
 2003-11-19  Atsushi Enomoto  <[email protected]>
 
 	* Added XPathComparer.cs

+ 27 - 3
mcs/class/System.XML/System.Xml.XPath/Expression.cs

@@ -448,6 +448,8 @@ namespace System.Xml.XPath
 			}
 			return Evaluate (iter);
 		}
+
+		public virtual bool RequireSorting { get { return false; } }
 	}
 
 	internal abstract class ExprBinary : Expression
@@ -841,6 +843,8 @@ namespace System.Xml.XPath
 			BaseIterator iterLeft = left.EvaluateNodeSet (iter);
 			return new SlashIterator (iterLeft, right);
 		}
+
+		public override bool RequireSorting { get { return left.RequireSorting || right.RequireSorting; } }
 	}
 	
 	internal class ExprSLASH2 : NodeSet {
@@ -865,6 +869,8 @@ namespace System.Xml.XPath
 				right
 			);
 		}
+
+		public override bool RequireSorting { get { return left.RequireSorting || right.RequireSorting; } }
 	}
 
 	internal class ExprRoot : NodeSet
@@ -1004,6 +1010,21 @@ namespace System.Xml.XPath
 		}
 		
 		public abstract void GetInfo (out string name, out string ns, out XPathNodeType nodetype, XmlNamespaceManager nsm);
+
+		public override bool RequireSorting {
+			get {
+				switch (_axis.Axis) {
+				case Axes.Ancestor:
+				case Axes.AncestorOrSelf:
+				case Axes.Preceding:
+				case Axes.PrecedingSibling:
+					return true;
+				default:
+					return false;
+				}
+			}
+
+		}
 	}
 
 	internal class NodeTypeTest : NodeTest
@@ -1261,7 +1282,6 @@ namespace System.Xml.XPath
 		}
 	}
 
-#if false
 	internal class ExprParens : Expression
 	{
 		protected Expression _expr;
@@ -1273,10 +1293,14 @@ namespace System.Xml.XPath
 		public override XPathResultType ReturnType { get { return _expr.ReturnType; }}
 		public override object Evaluate (BaseIterator iter)
 		{
-			return _expr.Evaluate (new ParensIterator (iter));
+			object o = (_expr.Evaluate (iter));
+			BaseIterator predBase = o as BaseIterator;
+			if (predBase != null)
+				return new ParensIterator (predBase);
+			else
+				return o;
 		}
 	}
-#endif
 
 	internal class FunctionArguments
 	{

+ 282 - 70
mcs/class/System.XML/System.Xml.XPath/Iterator.cs

@@ -38,6 +38,8 @@ namespace System.Xml.XPath
 			get { return false; }
 		}
 
+		public abstract bool RequireSorting { get; }
+
 		public virtual int ComparablePosition {
 			get {
 				if (ReverseAxis) {
@@ -104,20 +106,28 @@ namespace System.Xml.XPath
 			}
 		}
 		public override int CurrentPosition { get { return _pos; }}
+
+		public override bool RequireSorting { get { return true; } }
 	}
 
 	internal abstract class SimpleIterator : BaseIterator
 	{
+		protected readonly BaseIterator _iter;
 		protected readonly XPathNavigator _nav;
 		protected int _pos;
 
 		public SimpleIterator (BaseIterator iter) : base (iter)
 		{
-			_nav = iter.Current.Clone ();
+			_iter = iter;
+			if (iter.Current != null)
+				_nav = iter.Current.Clone ();
 		}
 		protected SimpleIterator (SimpleIterator other) : base (other)
 		{
-			_nav = other._nav.Clone ();
+			if (other._nav == null)
+				_iter = (BaseIterator) other._iter.Clone ();
+			else
+				_nav = other._nav.Clone ();
 			_pos = other._pos;
 		}
 		public SimpleIterator (XPathNavigator nav, XmlNamespaceManager nsm) : base (nsm)
@@ -144,6 +154,8 @@ namespace System.Xml.XPath
 			}
 			return false;
 		}
+
+		public override bool RequireSorting { get { return false; } }
 	}
 
 	internal class NullIterator : SelfIterator
@@ -159,6 +171,29 @@ namespace System.Xml.XPath
 		}
 	}
 
+	internal class ParensIterator : SimpleIterator
+	{
+		BaseIterator _iter;
+		public ParensIterator (BaseIterator iter) : base (iter) 
+		{
+			_iter = iter;
+		}
+		protected ParensIterator (ParensIterator other) : base (other) 
+		{
+			_iter = (BaseIterator) other._iter.Clone ();
+		}
+		public override XPathNodeIterator Clone () { return new ParensIterator (this); }
+		public override bool MoveNext ()
+		{
+			return _iter.MoveNext ();
+		}
+
+		public override XPathNavigator Current { get { return _iter.Current; }}
+		public override int CurrentPosition { get { return _iter.CurrentPosition; } }
+
+		public override bool RequireSorting { get { return _iter.RequireSorting; } }
+	}
+
 	internal class ParentIterator : SimpleIterator
 	{
 		public ParentIterator (BaseIterator iter) : base (iter) {}
@@ -174,6 +209,8 @@ namespace System.Xml.XPath
 			}
 			return false;
 		}
+
+		public override bool RequireSorting { get { return true; } }
 	}
 
 	internal class ChildIterator : SimpleIterator
@@ -188,6 +225,8 @@ namespace System.Xml.XPath
 				_pos ++;
 			return fSuccess;
 		}
+
+		public override bool RequireSorting { get { return false; } }
 	}
 
 	internal class FollowingSiblingIterator : SimpleIterator
@@ -197,6 +236,12 @@ namespace System.Xml.XPath
 		public override XPathNodeIterator Clone () { return new FollowingSiblingIterator (this); }
 		public override bool MoveNext ()
 		{
+			switch (_nav.NodeType) {
+			case XPathNodeType.Attribute:
+			case XPathNodeType.Namespace:
+				// They have no siblings.
+				return false;
+			}
 			if (_nav.MoveToNext ())
 			{
 				_pos ++;
@@ -204,6 +249,8 @@ namespace System.Xml.XPath
 			}
 			return false;
 		}
+
+		public override bool RequireSorting { get { return false; } }
 	}
 
 	internal class PrecedingSiblingIterator : SimpleIterator
@@ -230,6 +277,14 @@ namespace System.Xml.XPath
 				return false;
 			if (!started) {
 				started = true;
+				switch (_nav.NodeType) {
+				case XPathNodeType.Attribute:
+				case XPathNodeType.Namespace:
+					// They have no siblings.
+					finished = true;
+					return false;
+				}
+
 				_nav.MoveToFirst ();
 				if (_nav.ComparePosition (startPosition) == XmlNodeOrder.Same) {
 					_pos++;
@@ -253,6 +308,8 @@ namespace System.Xml.XPath
 		public override bool ReverseAxis {
 			get { return true; }
 		}
+
+		public override bool RequireSorting { get { return true; } }
 	}
 
 	internal class AncestorIterator : SimpleIterator
@@ -271,7 +328,7 @@ namespace System.Xml.XPath
 			startPosition = other.startPosition;
 			started = other.started;
 			finished = other.finished;
-			positions = other.positions;
+			positions = (ArrayList) other.positions.Clone ();
 			nextDepth = other.nextDepth;
 		}
 		public override XPathNodeIterator Clone () { return new AncestorIterator (this); }
@@ -284,7 +341,7 @@ namespace System.Xml.XPath
 				XPathNavigator ancestors = startPosition.Clone ();
 				ancestors.MoveToParent ();
 				_nav.MoveToParent ();
-				do {
+				while (ancestors.NodeType != XPathNodeType.Root) {
 					int i = 0;
 					_nav.MoveToFirst ();
 					while (_nav.ComparePosition (ancestors) == XmlNodeOrder.Before) {
@@ -294,8 +351,16 @@ namespace System.Xml.XPath
 					positions.Add (i);
 					ancestors.MoveToParent ();
 					_nav.MoveToParent ();
-				} while (ancestors.NodeType != XPathNodeType.Root);
+				}
+
+
 				positions.Reverse ();
+
+				if (startPosition.NodeType != XPathNodeType.Root) {
+					// First time it returns Root
+					_pos++;
+					return true;
+				}
 			}
 			if (nextDepth < positions.Count) {
 				int thisTimePos = (int) positions [nextDepth];
@@ -313,6 +378,8 @@ namespace System.Xml.XPath
 		public override bool ReverseAxis {
 			get { return true; }
 		}
+
+		public override bool RequireSorting { get { return true; } }
 	}
 
 	internal class AncestorOrSelfIterator : SimpleIterator
@@ -331,7 +398,7 @@ namespace System.Xml.XPath
 			startPosition = other.startPosition;
 			started = other.started;
 			finished = other.finished;
-			positions = other.positions;
+			positions = (ArrayList) other.positions.Clone ();
 			nextDepth = other.nextDepth;
 		}
 		public override XPathNodeIterator Clone () { return new AncestorOrSelfIterator (this); }
@@ -371,6 +438,8 @@ namespace System.Xml.XPath
 		public override bool ReverseAxis {
 			get { return true; }
 		}
+
+		public override bool RequireSorting { get { return true; } }
 	}
 
 	internal class DescendantIterator : SimpleIterator
@@ -413,6 +482,8 @@ namespace System.Xml.XPath
 			_finished = true;
 			return false;
 		}
+
+		public override bool RequireSorting { get { return false; } }
 	}
 
 	internal class DescendantOrSelfIterator : SimpleIterator
@@ -461,6 +532,8 @@ namespace System.Xml.XPath
 			_finished = true;
 			return false;
 		}
+
+		public override bool RequireSorting { get { return false; } }
 	}
 
 	internal class FollowingIterator : SimpleIterator
@@ -479,6 +552,13 @@ namespace System.Xml.XPath
 				{
 					_pos ++;
 					return true;
+				} else {
+					while (_nav.MoveToParent ()) {
+						if (_nav.MoveToNext ()) {
+							_pos ++;
+							return true;
+						}
+					}
 				}
 			}
 			else
@@ -501,6 +581,8 @@ namespace System.Xml.XPath
 			_finished = true;
 			return false;
 		}
+
+		public override bool RequireSorting { get { return false; } }
 	}
 
 	internal class PrecedingIterator : SimpleIterator
@@ -527,17 +609,18 @@ namespace System.Xml.XPath
 			if (!started) {
 				started = true;
 				_nav.MoveToRoot ();
-				_nav.MoveToFirstChild ();
-				if (_nav.ComparePosition (startPosition) == XmlNodeOrder.Same) {
-					_pos++;
-					return true;
-				}
-			} else {
+			}
+			bool loop = true;
+			while (loop) {
 				while (!_nav.MoveToFirstChild ()) {
 					while (!_nav.MoveToNext ())
 						_nav.MoveToParent (); // Should not finish, at least before startPosition.
 					break;
 				}
+				if (_nav.IsDescendant (startPosition))
+					continue;
+				loop = false;
+				break;
 			}
 			if (_nav.ComparePosition (startPosition) != XmlNodeOrder.Before) {
 				// Note that if _nav contains only 1 node, it won't be Same.
@@ -551,6 +634,8 @@ namespace System.Xml.XPath
 		public override bool ReverseAxis {
 			get { return true; }
 		}
+
+		public override bool RequireSorting { get { return true; } }
 	}
 
 	internal class NamespaceIterator : SimpleIterator
@@ -575,6 +660,8 @@ namespace System.Xml.XPath
 			}
 			return false;
 		}
+
+		public override bool RequireSorting { get { return false; } }
 	}
 
 	internal class AttributeIterator : SimpleIterator
@@ -599,6 +686,8 @@ namespace System.Xml.XPath
 			}
 			return false;			
 		}
+
+		public override bool RequireSorting { get { return false; } }
 	}
 
 	internal class AxisIterator : BaseIterator
@@ -647,7 +736,6 @@ namespace System.Xml.XPath
 		}
 		public override XPathNavigator Current { get { return _iter.Current; }}
 		public override int CurrentPosition { get { return _pos; }}
-		//public override int ComparablePosition { get { return _iter.ComparablePosition; } }
 		
 		bool Match ()
 		{
@@ -660,6 +748,11 @@ namespace System.Xml.XPath
 				return (object)ns == (object)Current.NamespaceURI &&
 					(name == null || (object)name == (object)Current.LocalName);
 		}
+		public override bool ReverseAxis {
+			get { return _iter.ReverseAxis; }
+		}
+
+		public override bool RequireSorting { get { return _iter.RequireSorting; } }
 	}
 
 #if false
@@ -713,7 +806,9 @@ namespace System.Xml.XPath
 		protected BaseIterator _iterRight;
 		protected NodeSet _expr;
 		protected int _pos;
-		Stack _iterStack;
+//		Stack _iterStack;
+		ArrayList _navStore;//(XPathIteratorComparer.Instance);
+		SortedList _iterList;
 		bool _finished;
 		BaseIterator _nextIterRight;
 
@@ -730,8 +825,10 @@ namespace System.Xml.XPath
 				_iterRight = (BaseIterator) other._iterRight.Clone ();
 			_expr = other._expr;
 			_pos = other._pos;
-			if (other._iterStack != null)
-				_iterStack = other._iterStack.Clone () as Stack;
+			if (other._iterList != null)
+				_iterList = other._iterList.Clone () as SortedList;
+			if (other._navStore != null)
+				_navStore = other._navStore.Clone () as ArrayList;
 			_finished = other._finished;
 			_nextIterRight = other._nextIterRight;
 		}
@@ -741,73 +838,175 @@ namespace System.Xml.XPath
 		{
 			if (_finished)
 				return false;
-
-			if (_iterRight == null) {
-				if (!_iterLeft.MoveNext ())
-					return false;
-				_iterRight = _expr.EvaluateNodeSet (_iterLeft);
-				_iterStack = new Stack ();
-			}
-
-			while (true) {
-				while (!_iterRight.MoveNext ()) {
-					if (_iterStack.Count > 0) {
-						_iterRight = _iterStack.Pop () as BaseIterator;
-						break;
-					} else if (_nextIterRight != null) {
-						_iterRight = _nextIterRight;
-						_nextIterRight = null;
-						break;
-					} else if (!_iterLeft.MoveNext ()) {
+			if (RequireSorting) {
+				if (_pos <= 0) {
+					CollectResults ();
+					if (_navStore.Count == 0) {
 						_finished = true;
 						return false;
 					}
+				}
+				_pos++;
+				if (_navStore.Count < _pos) {
+					_finished = true;
+					_pos--;
+					return false;
+				}
+				while (_navStore.Count > _pos) {
+					if (((XPathNavigator) _navStore [_pos]).ComparePosition (
+						(XPathNavigator) _navStore [_pos - 1]) == XmlNodeOrder.Same)
+						_navStore.RemoveAt (_pos);
 					else
-						_iterRight = _expr.EvaluateNodeSet (_iterLeft);
+						break;
 				}
-				bool loop = true;
-				while (loop) {
-					loop = false;
-					if (_nextIterRight == null) {
-						bool noMoreNext = false;
-						while (_nextIterRight == null || !_nextIterRight.MoveNext ()) {
-							if(_iterLeft.MoveNext ())
-								_nextIterRight = _expr.EvaluateNodeSet (_iterLeft);
-							else {
-								noMoreNext = true;
-								break;
-							}
-						}
-						if (noMoreNext)
-							_nextIterRight = null; // FIXME: More efficient code. Maybe making noMoreNext class scope would be better.
-					}
-					if (_nextIterRight != null) {
-						switch (_iterRight.Current.ComparePosition (_nextIterRight.Current)) {
-						case XmlNodeOrder.After:
-							_iterStack.Push (_iterRight);
-							_iterRight = _nextIterRight;
-							_nextIterRight = null;
-							break;
-						case XmlNodeOrder.Same:
-							if (!_nextIterRight.MoveNext ())
-								_nextIterRight = null;
-							loop = true;
-							break;
-						}
-					}
+
+				return true;
+			} else {
+#if false
+				while (_iterRight == null || !_iterRight.MoveNext ())
+				{
+					if (!_iterLeft.MoveNext ())
+						return false;
+					_iterRight = _expr.EvaluateNodeSet (_iterLeft);
 				}
 				_pos ++;
 				return true;
+#else
+				if (_iterRight == null) {
+					if (!_iterLeft.MoveNext ())
+						return false;
+					_iterRight = _expr.EvaluateNodeSet (_iterLeft);
+					_iterList = new SortedList (XPathIteratorComparer.Instance);
+				}
+
+				while (true) {
+					while (!_iterRight.MoveNext ()) {
+						if (_iterList.Count > 0) {
+							int last = _iterList.Count - 1;
+							BaseIterator tmpIter = _iterList.GetByIndex (last) as BaseIterator;
+							_iterList.RemoveAt (last);
+							switch (tmpIter.Current.ComparePosition (_iterRight.Current)) {
+							case XmlNodeOrder.Same:
+							case XmlNodeOrder.Before:
+								_iterRight = tmpIter;
+								continue;
+							default:
+								_iterRight = tmpIter;
+								break;
+							}
+							break;
+						} else if (_nextIterRight != null) {
+							_iterRight = _nextIterRight;
+							_nextIterRight = null;
+							break;
+						} else if (!_iterLeft.MoveNext ()) {
+							_finished = true;
+							return false;
+						}
+						else
+							_iterRight = _expr.EvaluateNodeSet (_iterLeft);
+					}
+					bool loop = true;
+					while (loop) {
+						loop = false;
+						if (_nextIterRight == null) {
+							bool noMoreNext = false;
+							/*
+							if (_iterList.Count > 0) {
+								int last = _iterList.Count -1;
+								BaseIterator tmpIter = _iterList.GetByIndex (last) as BaseIterator;
+								_iterList.RemoveAt (last);
+								switch (tmpIter.Current.ComparePosition (_iterRight.Current)) {
+								case XmlNodeOrder.Same:
+								case XmlNodeOrder.Before:
+									_iterList.Add (_iterRight, _iterRight);
+									_iterRight = tmpIter;
+									break;
+								default:
+									_iterList.Add (_iterRight, _iterRight);
+									break;
+								}
+							}
+							*/
+							while (_nextIterRight == null || !_nextIterRight.MoveNext ()) {
+								if(_iterLeft.MoveNext ())
+									_nextIterRight = _expr.EvaluateNodeSet (_iterLeft);
+								else {
+									noMoreNext = true;
+									break;
+								}
+							}
+							if (noMoreNext)
+								_nextIterRight = null; // FIXME: More efficient code. Maybe making noMoreNext class scope would be better.
+						}
+						if (_nextIterRight != null) {
+							switch (_iterRight.Current.ComparePosition (_nextIterRight.Current)) {
+							case XmlNodeOrder.After:
+								_iterList.Add (_iterList.Count, _iterRight);
+								_iterRight = _nextIterRight;
+								_nextIterRight = null;
+								loop = true;
+								break;
+							case XmlNodeOrder.Same:
+								if (!_nextIterRight.MoveNext ())
+									_nextIterRight = null;
+
+								else {
+									int last = _iterList.Count;
+									if (last > 0) {
+										_iterList.Add (last, _nextIterRight);
+										_nextIterRight = _iterList.GetByIndex (last) as BaseIterator;
+										_iterList.RemoveAt (last);
+									}
+								}
+
+								loop = true;
+								break;
+							}
+						}
+					}
+					_pos ++;
+					return true;
+				}
+#endif
 			}
 		}
+		private void CollectResults ()
+		{
+			if (_navStore != null)
+				return;
+			_navStore = new ArrayList ();
+			while (true) {
+				while (_iterRight == null || !_iterRight.MoveNext ()) {
+					if (!_iterLeft.MoveNext ()) {
+						_navStore.Sort (XPathNavigatorComparer.Instance);
+						return;
+					}
+					_iterRight = _expr.EvaluateNodeSet (_iterLeft);
+				}
+				XPathNavigator nav = _iterRight.Current.Clone ();
+				_navStore.Add (nav);
+			}
+		}
+
 		public override XPathNavigator Current { 
-			get { 
-				if (_iterRight == null) return null;
-				
-				return _iterRight.Current;
+			get {
+				if (_pos <= 0) return null;
+				if (RequireSorting) {
+					return _navStore [_pos - 1] as XPathNavigator;
+				} else {
+					return _iterRight.Current;
+				}
 			}
 		}
 		public override int CurrentPosition { get { return _pos; }}
+
+		public override bool RequireSorting {
+			get {
+				// FIXME: consider _exprRight (but without collecting).
+				return _iterLeft.RequireSorting || _expr.RequireSorting;
+			}
+		}
 	}
 
 #endif
@@ -870,6 +1069,11 @@ namespace System.Xml.XPath
 		}
 		public override XPathNavigator Current { get { return _iter.Current; }}
 		public override int CurrentPosition { get { return _pos; }}
+		public override bool ReverseAxis {
+			get { return _iter.ReverseAxis; }
+		}
+
+		public override bool RequireSorting { get { return true; } }
 	}
 
 	internal class EnumeratorIterator : BaseIterator
@@ -889,7 +1093,10 @@ namespace System.Xml.XPath
 
 		protected EnumeratorIterator (EnumeratorIterator other) : base (other)
 		{
-			_enum = other._enum;
+			ICloneable enumClone = other._enum as ICloneable;
+			if (enumClone == null)
+				throw new ArgumentException ("Enumerator must be cloneable.");
+			_enum = enumClone.Clone () as IEnumerator;
 			_pos = other._pos;
 		}
 		public override XPathNodeIterator Clone () { return new EnumeratorIterator (this); }
@@ -903,6 +1110,8 @@ namespace System.Xml.XPath
 		}
 		public override XPathNavigator Current { get { return (XPathNavigator) _enum.Current; }}
 		public override int CurrentPosition { get { return _pos; }}
+
+		public override bool RequireSorting { get { return true; } }
 	}
 
 
@@ -955,6 +1164,7 @@ namespace System.Xml.XPath
 				useRight = true;
 				return true;
 			case XmlNodeOrder.Before:
+			case XmlNodeOrder.Unknown: // Maybe happen because of "document(a) | document(b)"
 				keepLeft = useRight = false;
 				return true;
 			case XmlNodeOrder.After:
@@ -978,5 +1188,7 @@ namespace System.Xml.XPath
 			}
 		}
 		public override int CurrentPosition { get { return _pos; }}
+
+		public override bool RequireSorting { get { return _left.RequireSorting || _right.RequireSorting; } }
 	}
 }

+ 1 - 1
mcs/class/System.XML/System.Xml.XPath/Parser.jay

@@ -335,7 +335,7 @@ PrimaryExpr
 	}
 	| PAREN_OPEN Expr PAREN_CLOSE
 	{
-		$$ = $2;
+		$$ = new ExprParens ((Expression) $2);
 	}
 	| LITERAL
 	{