New test.
[mono.git] / mcs / class / Commons.Xml.Relaxng / Commons.Xml.Relaxng.Derivative / RdpPatterns.cs
index 0463d4cc103b8f8cce52bcdb3c1b99bb93c7f964..a729b8db56bc0f70d9a9fe8b0121478af1b7b579 100644 (file)
@@ -125,6 +125,8 @@ namespace Commons.Xml.Relaxng.Derivative
                                return p2;
                        if (p2.PatternType == RelaxngPatternType.NotAllowed)
                                return p1;
+                       if (p1 == p2)
+                               return p1;
                        // choice-leaves support
                        if (p1.PatternType == RelaxngPatternType.Empty)
                                return MakeChoiceLeaf (p2);
@@ -294,6 +296,10 @@ namespace Commons.Xml.Relaxng.Derivative
                        get { return false; }
                }
 
+               internal virtual bool IsContextDependent {
+                       get { return false; }
+               }
+
                // fills QName collection
                public void GetLabels (LabelList elements, LabelList attributes)
                {
@@ -326,6 +332,16 @@ namespace Commons.Xml.Relaxng.Derivative
                        return RdpNotAllowed.Instance;
                }
 
+               internal virtual RdpPattern TextDeriv (string s, XmlReader reader, MemoizationStore memo)
+               {
+                       return TextDeriv (s, reader);
+               }
+
+               internal virtual RdpPattern EmptyTextDeriv (MemoizationStore memo)
+               {
+                       return TextDeriv (String.Empty, null, memo);
+               }
+
                internal virtual RdpPattern TextOnlyDeriv ()
                {
                        return this;
@@ -506,6 +522,10 @@ namespace Commons.Xml.Relaxng.Derivative
                        get { return false; }
                }
 
+               internal override bool IsContextDependent {
+                       get { return false; }
+               }
+
                static RdpEmpty instance;
                public static RdpEmpty Instance {
                        get { return instance; }
@@ -563,6 +583,10 @@ namespace Commons.Xml.Relaxng.Derivative
                        get { return false; }
                }
 
+               internal override bool IsContextDependent {
+                       get { return false; }
+               }
+
                public override RdpPattern ApplyAfter (RdpApplyAfterHandler h)
                {
                        return RdpNotAllowed.Instance;
@@ -619,6 +643,10 @@ namespace Commons.Xml.Relaxng.Derivative
                        get { return false; }
                }
 
+               internal override bool IsContextDependent {
+                       get { return false; }
+               }
+
                public override RelaxngPatternType PatternType {
                        get { return RelaxngPatternType.Text; }
                }
@@ -632,6 +660,11 @@ namespace Commons.Xml.Relaxng.Derivative
                        return this;
                }
 
+               internal override RdpPattern EmptyTextDeriv (MemoizationStore memo)
+               {
+                       return this;
+               }
+
                internal override RdpPattern MixedTextDeriv ()
                {
                        return this;
@@ -791,6 +824,19 @@ namespace Commons.Xml.Relaxng.Derivative
                        }
                }
 
+               bool isContextDependentComputed;
+               bool isContextDependent;
+
+               internal override bool IsContextDependent {
+                       get {
+                               if (!isContextDependentComputed) {
+                                       isContextDependent = LValue.IsContextDependent || RValue.IsContextDependent;
+                                       isContextDependentComputed = true;
+                               }
+                               return isContextDependent;
+                       }
+               }
+
                public override RelaxngPatternType PatternType {
                        get { return RelaxngPatternType.Choice; }
                }
@@ -853,6 +899,17 @@ namespace Commons.Xml.Relaxng.Derivative
                        return LValue.TextDeriv (s, reader).Choice (RValue.TextDeriv (s, reader));
                }
 
+               internal override RdpPattern TextDeriv (string s, XmlReader reader, MemoizationStore memo)
+               {
+                       return memo.TextDeriv (LValue, s, reader).Choice (memo.TextDeriv (RValue, s, reader));
+               }
+
+               internal override RdpPattern EmptyTextDeriv (MemoizationStore memo)
+               {
+                       return memo.EmptyTextDeriv (LValue)
+                               .Choice (memo.EmptyTextDeriv (RValue));
+               }
+
                internal override RdpPattern TextOnlyDeriv ()
                {
                        return LValue.TextOnlyDeriv ().Choice (
@@ -984,6 +1041,10 @@ namespace Commons.Xml.Relaxng.Derivative
                        get { return LValue.IsTextValueDependent || RValue.IsTextValueDependent; }
                }
 
+               internal override bool IsContextDependent {
+                       get { return LValue.IsContextDependent || RValue.IsContextDependent; }
+               }
+
                public override void GetLabels (LabelList elements, LabelList attributes, bool collectNameClass)
                {
                        LValue.GetLabels (elements, attributes, collectNameClass);
@@ -1013,6 +1074,18 @@ namespace Commons.Xml.Relaxng.Derivative
                                .Choice (LValue.Interleave (RValue.TextDeriv (s, reader)));
                }
 
+               internal override RdpPattern TextDeriv (string s, XmlReader reader, MemoizationStore memo)
+               {
+                       return memo.TextDeriv (LValue, s, reader).Interleave (RValue)
+                               .Choice (LValue.Interleave (memo.TextDeriv (RValue, s, reader)));
+               }
+
+               internal override RdpPattern EmptyTextDeriv (MemoizationStore memo)
+               {
+                       return memo.EmptyTextDeriv (LValue).Interleave (RValue)
+                               .Choice (LValue.Interleave (memo.EmptyTextDeriv (RValue)));
+               }
+
                internal override RdpPattern TextOnlyDeriv ()
                {
                        return LValue.TextOnlyDeriv ().Interleave (
@@ -1150,6 +1223,10 @@ namespace Commons.Xml.Relaxng.Derivative
                        get { return LValue.IsTextValueDependent || (LValue.Nullable ? RValue.IsTextValueDependent : false); }
                }
 
+               internal override bool IsContextDependent {
+                       get { return LValue.IsContextDependent || (LValue.Nullable ? RValue.IsContextDependent : false); }
+               }
+
                public override void GetLabels (LabelList elements, LabelList attributes, bool collectNameClass)
                {
                        LValue.GetLabels (elements, attributes, collectNameClass);
@@ -1161,21 +1238,43 @@ namespace Commons.Xml.Relaxng.Derivative
 
                public override RdpPattern TextDeriv (string s, XmlReader reader)
                {
-                       RdpPattern p = LValue.TextDeriv (s, reader).Group (RValue);
+                       RdpPattern p = LValue.TextDeriv (s, reader);
+                       p = (p.PatternType == RelaxngPatternType.NotAllowed) ?
+                               p : p.Group (RValue);
                        return LValue.Nullable ?
                                p.Choice (RValue.TextDeriv (s, reader)) : p;
                }
 
+               internal override RdpPattern TextDeriv (string s, XmlReader reader, MemoizationStore memo)
+               {
+                       RdpPattern p = memo.TextDeriv (LValue, s, reader);
+                       p = (p.PatternType == RelaxngPatternType.NotAllowed) ?
+                               p : p.Group (RValue);
+                       return LValue.Nullable ?
+                               p.Choice (memo.TextDeriv (RValue, s, reader)) : p;
+               }
+
+               internal override RdpPattern EmptyTextDeriv (MemoizationStore memo)
+               {
+                       RdpPattern p = memo.EmptyTextDeriv (LValue);
+                       p = p.PatternType == RelaxngPatternType.NotAllowed ?
+                               p : p.Group (RValue);
+                       return LValue.Nullable ?
+                               p.Choice (memo.EmptyTextDeriv (RValue)) : p;
+               }
+
                internal override RdpPattern TextOnlyDeriv ()
                {
-                       return LValue.TextOnlyDeriv ().Group (
-                               RValue.TextOnlyDeriv ());
+                       RdpPattern p = LValue.TextOnlyDeriv ();
+                       return p.PatternType == RelaxngPatternType.NotAllowed ?
+                               p : p.Group (RValue.TextOnlyDeriv ());
                }
 
                internal override RdpPattern TextOnlyDeriv (MemoizationStore memo)
                {
-                       return memo.TextOnlyDeriv (LValue).Group (
-                               memo.TextOnlyDeriv (RValue));
+                       RdpPattern p = memo.TextOnlyDeriv (LValue);
+                       return p.PatternType == RelaxngPatternType.NotAllowed ?
+                               p : p.Group (memo.TextOnlyDeriv (RValue));
                }
 
                internal override RdpPattern MixedTextDeriv ()
@@ -1255,14 +1354,16 @@ namespace Commons.Xml.Relaxng.Derivative
                //  group (startTagCloseDeriv p1) (startTagCloseDeriv p2)
                public override RdpPattern StartTagCloseDeriv ()
                {
-                       return LValue.StartTagCloseDeriv ()
-                               .Group (RValue.StartTagCloseDeriv ());
+                       RdpPattern p = LValue.StartTagCloseDeriv ();
+                       return p.PatternType == RelaxngPatternType.NotAllowed ?
+                               p : p.Group (RValue.StartTagCloseDeriv ());
                }
 
                internal override RdpPattern StartTagCloseDeriv (MemoizationStore memo)
                {
-                       return memo.StartTagCloseDeriv (LValue)
-                               .Group (memo.StartTagCloseDeriv (RValue));
+                       RdpPattern p = memo.StartTagCloseDeriv (LValue);
+                       return p.PatternType == RelaxngPatternType.NotAllowed ?
+                               p : p.Group (memo.StartTagCloseDeriv (RValue));
                }
 
                public override RelaxngPatternType PatternType {
@@ -1342,6 +1443,10 @@ namespace Commons.Xml.Relaxng.Derivative
                        get { return Child.IsTextValueDependent; }
                }
 
+               internal override bool IsContextDependent {
+                       get { return Child.IsContextDependent; }
+               }
+
                public override void GetLabels (LabelList elements, LabelList attributes, bool collectNameClass)
                {
                        Child.GetLabels (elements, attributes, collectNameClass);
@@ -1366,7 +1471,23 @@ namespace Commons.Xml.Relaxng.Derivative
 
                public override RdpPattern TextDeriv (string s, XmlReader reader)
                {
-                       return Child.TextDeriv (s, reader).Group (this.Choice (RdpEmpty.Instance));
+                       RdpPattern p = Child.TextDeriv (s, reader);
+                       return p.PatternType == RelaxngPatternType.NotAllowed ?
+                               p : p.Group (this.Choice (RdpEmpty.Instance));
+               }
+
+               internal override RdpPattern TextDeriv (string s, XmlReader reader, MemoizationStore memo)
+               {
+                       RdpPattern p = memo.TextDeriv (Child, s, reader);
+                       return p.PatternType == RelaxngPatternType.NotAllowed ?
+                               p : p.Group (this.Choice (RdpEmpty.Instance));
+               }
+
+               internal override RdpPattern EmptyTextDeriv (MemoizationStore memo)
+               {
+                       RdpPattern p = memo.EmptyTextDeriv (Child);
+                       return p.PatternType == RelaxngPatternType.NotAllowed ?
+                               p : p.Group (this.Choice (RdpEmpty.Instance));
                }
 
                internal override RdpPattern TextOnlyDeriv ()
@@ -1381,28 +1502,25 @@ namespace Commons.Xml.Relaxng.Derivative
 
                internal override RdpPattern MixedTextDeriv ()
                {
-                       return Child.MixedTextDeriv ().Group (
-                               this.Choice (RdpEmpty.Instance));
+                       RdpPattern p = Child.MixedTextDeriv ();
+                       return p.PatternType == RelaxngPatternType.NotAllowed ?
+                               p : p.Group (this.Choice (RdpEmpty.Instance));
                }
 
                internal override RdpPattern MixedTextDeriv (MemoizationStore memo)
                {
-                       return memo.MixedTextDeriv (Child).Group (
-                               this.Choice (RdpEmpty.Instance));
+                       RdpPattern p = memo.MixedTextDeriv (Child);
+                       return p.PatternType == RelaxngPatternType.NotAllowed ?
+                               p : p.Group (this.Choice (RdpEmpty.Instance));
                }
 
                // attDeriv cx (OneOrMore p) att =
                //  group (attDeriv cx p att) (choice (OneOrMore p) Empty)
                public override RdpPattern AttDeriv (string name, string ns, string value, XmlReader reader)
                {
-#if UseStatic
-                       return RdpUtil.Group (
-                               RdpUtil.AttDeriv (ctx, children, att),
-                               RdpUtil.Choice (RdpUtil.OneOrMore (children), RdpEmpty.Instance));
-#else
-                       return Child.AttDeriv (name, ns, value, reader)
-                               .Group (Choice (RdpEmpty.Instance));
-#endif
+                       RdpPattern p = Child.AttDeriv (name, ns, value, reader);
+                       return p.PatternType == RelaxngPatternType.NotAllowed ?
+                               p : p.Group (Choice (RdpEmpty.Instance));
                }
 
                // startTagOpenDeriv (OneOrMore p) qn =
@@ -1495,6 +1613,10 @@ namespace Commons.Xml.Relaxng.Derivative
                        get { return true; }
                }
 
+               internal override bool IsContextDependent {
+                       get { return Child.IsContextDependent; }
+               }
+
                public override RelaxngPatternType PatternType {
                        get { return RelaxngPatternType.List; }
                }
@@ -1550,6 +1672,10 @@ namespace Commons.Xml.Relaxng.Derivative
                        get { return true; }
                }
 
+               internal override bool IsContextDependent {
+                       get { return dt.IsContextDependent; }
+               }
+
                public override RelaxngPatternType PatternType {
                        get { return RelaxngPatternType.Data; }
                }
@@ -1674,6 +1800,10 @@ namespace Commons.Xml.Relaxng.Derivative
                        get { return true; }
                }
 
+               internal override bool IsContextDependent {
+                       get { return dt.IsContextDependent; }
+               }
+
                public override RelaxngPatternType PatternType {
                        get { return RelaxngPatternType.Value; }
                }
@@ -1687,7 +1817,19 @@ namespace Commons.Xml.Relaxng.Derivative
                        // do nothing
                }
 
+               string cachedValue;
+               RdpPattern cachedPattern;
+
                public override RdpPattern TextDeriv (string s, XmlReader reader)
+               {
+                       if (s == cachedValue && !IsContextDependent)
+                               return cachedPattern;
+                       cachedPattern = TextDerivCore (s, reader);
+                       cachedValue = s;
+                       return cachedPattern;
+               }
+
+               RdpPattern TextDerivCore (string s, XmlReader reader)
                {
                        if (dt.IsTypeEqual (value, s, reader))
                                return RdpEmpty.Instance;
@@ -1739,6 +1881,10 @@ namespace Commons.Xml.Relaxng.Derivative
                        get { return false; }
                }
 
+               internal override bool IsContextDependent {
+                       get { return false; }
+               }
+
                public override RelaxngPatternType PatternType {
                        get { return RelaxngPatternType.Attribute; }
                }
@@ -1879,6 +2025,10 @@ namespace Commons.Xml.Relaxng.Derivative
                        get { return false; }
                }
 
+               internal override bool IsContextDependent {
+                       get { return false; }
+               }
+
                public override RelaxngPatternType PatternType {
                        get { return RelaxngPatternType.Element; }
                }
@@ -1999,6 +2149,10 @@ namespace Commons.Xml.Relaxng.Derivative
                        get { return LValue.IsTextValueDependent; }
                }
 
+               internal override bool IsContextDependent {
+                       get { return LValue.IsContextDependent; }
+               }
+
                public override void GetLabels (LabelList elements, LabelList attributes, bool collectNameClass)
                {
                        LValue.GetLabels (elements, attributes, collectNameClass);
@@ -2009,6 +2163,16 @@ namespace Commons.Xml.Relaxng.Derivative
                        return LValue.TextDeriv (s, reader).After (RValue);
                }
 
+               internal override RdpPattern TextDeriv (string s, XmlReader reader, MemoizationStore memo)
+               {
+                       return memo.TextDeriv (LValue, s, reader).After (RValue);
+               }
+
+               internal override RdpPattern EmptyTextDeriv (MemoizationStore memo)
+               {
+                       return memo.EmptyTextDeriv (LValue).After (RValue);
+               }
+
                internal override RdpPattern TextOnlyDeriv ()
                {
                        return LValue.TextOnlyDeriv ().After (RValue);