-//\r
-// Commons.Xml.Relaxng.Derivative.RdpPatterns.cs\r
-//\r
-// Author:\r
-// Atsushi Enomoto <ginga@kit.hi-ho.ne.jp>\r
-//\r
-// 2003 Atsushi Enomoto "No rights reserved."\r
-//\r
-// Copyright (c) 2004 Novell Inc.\r
-// All rights reserved\r
-//\r
+//
+// Commons.Xml.Relaxng.Derivative.RdpPatterns.cs
+//
+// Author:
+// Atsushi Enomoto <ginga@kit.hi-ho.ne.jp>
+//
+// 2003 Atsushi Enomoto "No rights reserved."
+//
+// Copyright (c) 2004 Novell Inc.
+// All rights reserved
+//
//
// Permission is hereby granted, free of charge, to any person obtaining
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
-\r
-using System;\r
-using System.Collections;\r
-using System.Xml;\r
-using Commons.Xml.Relaxng;\r
-\r
-using LabelList = System.Collections.Hashtable;\r
-\r
-\r
-namespace Commons.Xml.Relaxng.Derivative\r
-{\r
- public delegate RdpPattern RdpApplyAfterHandler (RdpPattern p);\r
-\r
- // abstract Pattern\r
- public abstract class RdpPattern\r
- {\r
- internal bool nullableComputed;\r
- internal bool isNullable;\r
- Hashtable patternPool;\r
-\r
- internal string debug ()\r
- {\r
- return RdpUtil.DebugRdpPattern (this, new Hashtable ());\r
- }\r
-\r
- public abstract RelaxngPatternType PatternType { get; }\r
-\r
- public abstract RdpContentType ContentType { get; }\r
-\r
- private Hashtable setupTable (Type type, RdpPattern p)\r
- {\r
- // Why?\r
- if (patternPool == null) {\r
- patternPool = new Hashtable ();\r
- }\r
-\r
- Hashtable typePool = (Hashtable) patternPool [type];\r
- if (typePool == null) {\r
- typePool = new Hashtable ();\r
- patternPool [type] = typePool;\r
- }\r
- Hashtable pTable = (Hashtable) typePool [p];\r
- if (pTable == null) {\r
- pTable = new Hashtable ();\r
- typePool [p] = pTable;\r
- }\r
- return pTable;\r
- }\r
-\r
- public RdpChoice MakeChoice (RdpPattern p1, RdpPattern p2)\r
- {\r
- Hashtable p1Table = setupTable (typeof (RdpChoice), p1);\r
- if (p1Table [p2] == null) {\r
- RdpChoice c = new RdpChoice (p1, p2);\r
- c.setInternTable (this.patternPool);\r
- p1Table [p2] = c;\r
- }\r
- return (RdpChoice) p1Table [p2];\r
- }\r
-\r
- public RdpPattern MakeGroup (RdpPattern p1, RdpPattern p2)\r
- {\r
- Hashtable p1Table = setupTable (typeof (RdpGroup), p1);\r
- if (p1Table [p2] == null) {\r
- RdpGroup g = new RdpGroup (p1, p2);\r
- g.setInternTable (this.patternPool);\r
- p1Table [p2] = g;\r
- }\r
- return (RdpGroup) p1Table [p2];\r
- }\r
-\r
- public RdpInterleave MakeInterleave (RdpPattern p1, RdpPattern p2)\r
- {\r
- Hashtable p1Table = setupTable (typeof (RdpInterleave), p1);\r
- if (p1Table [p2] == null) {\r
- RdpInterleave i = new RdpInterleave (p1, p2);\r
- i.setInternTable (this.patternPool);\r
- p1Table [p2] = i;\r
- }\r
- return (RdpInterleave) p1Table [p2];\r
- }\r
-\r
- public RdpAfter MakeAfter (RdpPattern p1, RdpPattern p2)\r
- {\r
- Hashtable p1Table = setupTable (typeof (RdpAfter), p1);\r
- if (p1Table [p2] == null) {\r
- RdpAfter a = new RdpAfter (p1, p2);\r
- a.setInternTable (this.patternPool);\r
- p1Table [p2] = a;\r
- }\r
- return (RdpAfter) p1Table [p2];\r
- }\r
-\r
- public RdpOneOrMore MakeOneOrMore (RdpPattern p)\r
- {\r
- Hashtable p1Table = setupTable (typeof (RdpOneOrMore), p);\r
- Hashtable pTable = (Hashtable) patternPool [RelaxngPatternType.OneOrMore];\r
- if (pTable == null) {\r
- pTable = new Hashtable ();\r
- patternPool [RelaxngPatternType.OneOrMore] = pTable;\r
- }\r
- if (pTable [p] == null)\r
- pTable [p] = new RdpOneOrMore (p);\r
- return (RdpOneOrMore) pTable [p];\r
- }\r
-\r
- internal void setInternTable (Hashtable ht)\r
- {\r
- this.patternPool = ht;\r
-\r
- Hashtable pt = ht [PatternType] as Hashtable;\r
- if (pt == null) {\r
- pt = new Hashtable ();\r
- ht [PatternType] = pt;\r
- }\r
-\r
- RdpAbstractSingleContent single =\r
- this as RdpAbstractSingleContent;\r
- if (single != null) {\r
- if (pt [single.Child] == null) {\r
- pt [single.Child] = this;\r
- single.Child.setInternTable (ht);\r
- }\r
- return;\r
- }\r
-\r
- RdpAbstractBinary binary =\r
- this as RdpAbstractBinary;\r
- if (binary != null) {\r
- Hashtable lTable = setupTable (GetType (), binary.LValue);\r
- if (lTable [binary.RValue] == null) {\r
- lTable [binary.RValue] = this;\r
- binary.LValue.setInternTable (ht);\r
- binary.RValue.setInternTable (ht);\r
- }\r
- return;\r
- }\r
-\r
- // For rest patterns, only check recursively, without pooling.\r
- RdpAttribute attr = this as RdpAttribute;\r
- if (attr != null) {\r
- attr.Children.setInternTable (ht);\r
- return;\r
- }\r
- RdpElement el = this as RdpElement;\r
- if (el != null) {\r
- el.Children.setInternTable (ht);\r
- return;\r
- }\r
- RdpDataExcept dex= this as RdpDataExcept;\r
- if (dex != null) {\r
- dex.Except.setInternTable (ht);\r
- return;\r
- }\r
-\r
- switch (PatternType) {\r
- case RelaxngPatternType.Empty:\r
- case RelaxngPatternType.NotAllowed:\r
- case RelaxngPatternType.Text:\r
- case RelaxngPatternType.Data:\r
- case RelaxngPatternType.Value:\r
- return;\r
- }\r
-\r
-#if REPLACE_IN_ADVANCE\r
- throw new InvalidOperationException ();\r
-#endif\r
- }\r
-\r
- internal abstract void MarkReachableDefs ();\r
-\r
- internal abstract void CheckConstraints (bool attribute, bool oneOrMore, bool oneOrMoreGroup, bool oneOrMoreInterleave, bool list, bool dataExcept);\r
-\r
- internal virtual void CheckAttributeDuplicates ()\r
- {\r
- }\r
-\r
- internal abstract bool ContainsText ();\r
-\r
- internal virtual RdpPattern ExpandRef (Hashtable defs)\r
- {\r
- return this;\r
- }\r
-\r
- internal virtual RdpPattern ReduceEmptyAndNotAllowed (ref bool result, Hashtable visited)\r
- {\r
- return this;\r
- }\r
-\r
- public abstract bool Nullable { get; }\r
-\r
- // fills QName collection\r
- public abstract void GetLabels (LabelList elements, LabelList attributes);\r
-\r
- internal void AddNameLabel (LabelList names, RdpNameClass nc)\r
- {\r
- if (names == null)\r
- return;\r
- RdpName name = nc as RdpName;\r
- if (name != null) {\r
- XmlQualifiedName qname = new XmlQualifiedName (\r
- name.LocalName, name.NamespaceURI);\r
- names [qname] = qname;\r
- return;\r
- }\r
- RdpNameClassChoice choice = nc as RdpNameClassChoice;\r
- if (choice != null) {\r
- AddNameLabel (names, choice.LValue);\r
- AddNameLabel (names, choice.RValue);\r
- return;\r
- }\r
- // For NsName and AnyName, do nothing.\r
- }\r
-\r
- #region Derivative\r
- public virtual RdpPattern TextDeriv (string s, XmlReader reader)\r
- {\r
- // This is an extension to JJC algorithm.\r
- // Whitespace text are allowed except for Data and Value\r
- // (their TextDeriv are overridden)\r
- return Util.IsWhitespace (s) ? this : RdpNotAllowed.Instance;\r
- }\r
-\r
-/*\r
- public RdpPattern ChildDeriv (RdpChildNode child)\r
- {\r
- RdpTextChild tc = child as RdpTextChild;\r
-// RdpElementChild ec = child as RdpElementChild;\r
- if (tc != null) {\r
- return TextDeriv (tc.Text);\r
- } else {\r
- // complex stuff;-(\r
- return StartTagOpenDeriv (ec.LocalName, ec.NamespaceURI)\r
- .AttsDeriv (ec.Attributes)\r
- .StartTagCloseDeriv ()\r
- .ChildrenDeriv (ec.ChildNodes)\r
- .EndTagDeriv ();\r
- }\r
- }\r
-*/\r
-\r
- public RdpPattern ListDeriv (string [] list, int index, XmlReader reader)\r
- {\r
- return listDerivInternal (list, 0, reader);\r
- }\r
-\r
- private RdpPattern listDerivInternal (string [] list, int start, XmlReader reader)\r
- {\r
- if (list.Length <= start)\r
- return this;\r
- else\r
- return this.TextDeriv (list [start], reader).listDerivInternal (list, start + 1, reader);\r
- }\r
-\r
- // Choice(this, p)\r
- public virtual RdpPattern Choice (RdpPattern p)\r
- {\r
- if (p is RdpNotAllowed)\r
- return this;\r
- else if (this is RdpNotAllowed)\r
- return p;\r
- else\r
- return MakeChoice (this, p);\r
- }\r
-\r
- // Group(this, p)\r
- public virtual RdpPattern Group (RdpPattern p)\r
- {\r
- if (p is RdpNotAllowed || this is RdpNotAllowed)\r
- return RdpNotAllowed.Instance;\r
- else if (p is RdpEmpty)\r
- return this;\r
- else if (this is RdpEmpty)\r
- return p;\r
- else\r
- return MakeGroup (this, p);\r
- }\r
-\r
- // Interleave(this, p)\r
- public virtual RdpPattern Interleave (RdpPattern p)\r
- {\r
- if (p is RdpNotAllowed || this is RdpNotAllowed)\r
- return RdpNotAllowed.Instance;\r
- else if (p is RdpEmpty)\r
- return this;\r
- else if (this is RdpEmpty)\r
- return p;\r
- else\r
- return MakeInterleave (this, p);\r
- }\r
-\r
- // After(this, p)\r
- public virtual RdpPattern After (RdpPattern p)\r
- {\r
- if (this is RdpNotAllowed || p is RdpNotAllowed)\r
- return RdpNotAllowed.Instance;\r
- else\r
- return MakeAfter (this, p);\r
- }\r
-\r
-\r
- // applyAfter((f, p1=this), p2)\r
- public virtual RdpPattern ApplyAfter (RdpApplyAfterHandler h)\r
- {\r
- return RdpNotAllowed.Instance;\r
- }\r
-\r
- // startTagOpenDeriv (this, qname)\r
- // startTagOpenDeriv _ qn = NotAllowed (default)\r
- public virtual RdpPattern StartTagOpenDeriv (string name, string ns)\r
- {\r
- return RdpNotAllowed.Instance;\r
- }\r
-\r
- // attDeriv(ctx, this, att)\r
- // attDeriv _ _ _ = NotAllowed\r
- public virtual RdpPattern AttDeriv (string name, string ns, string value, XmlReader reader)\r
- {\r
- return RdpNotAllowed.Instance;\r
- }\r
-\r
- public bool ValueMatch (string s, XmlReader reader)\r
- {\r
- return (Nullable && RdpUtil.Whitespace (s)) ||\r
- TextDeriv (s, reader).Nullable;\r
- }\r
-\r
- public virtual RdpPattern StartTagCloseDeriv ()\r
- {\r
- return this;\r
- }\r
-\r
- /*\r
- public RdpPattern ChildrenDeriv (RdpChildNodes children)\r
- {\r
- return childrenDerivInternal (children, 0);\r
- }\r
-\r
- RdpPattern childrenDerivInternal (RdpChildNodes children, int start)\r
- {\r
- if (children.Count == 0) {\r
- // childrenDeriv cx p []\r
- RdpChildNodes c = new RdpChildNodes ();\r
- c.Add (new RdpTextChild (String.Empty));\r
- return ChildrenDeriv (c);\r
- } else if (children.Count == 1 && children [0] is RdpTextChild) {\r
- // childrenDeriv cx p [(TextNode s)]\r
- RdpTextChild tc = children [0] as RdpTextChild;\r
- RdpPattern p1 = ChildDeriv (tc);\r
- return RdpUtil.Whitespace (tc.Text) ?\r
- RdpUtil.Choice (this, p1) : p1;\r
- } else\r
- // childrenDeriv cx p children\r
- return stripChildrenDerivInternal (children, start);\r
- }\r
-\r
- RdpPattern stripChildrenDerivInternal (RdpChildNodes children, int start)\r
- {\r
- if (children.Count == start)\r
- return this;\r
- else {\r
- RdpChildNode firstChild =\r
- children [start] as RdpChildNode;\r
- RdpPattern p =\r
- (firstChild.IsNonWhitespaceText) ?\r
- this : ChildDeriv (firstChild);\r
- return p.childrenDerivInternal (children, start + 1);\r
- }\r
- }\r
- */\r
-\r
- public RdpPattern OneOrMore ()\r
- {\r
- if (PatternType == RelaxngPatternType.NotAllowed)\r
- return RdpNotAllowed.Instance;\r
- else\r
- return MakeOneOrMore (this);\r
- }\r
-\r
- public virtual RdpPattern EndTagDeriv ()\r
- {\r
- return RdpNotAllowed.Instance;\r
- }\r
- #endregion\r
- }\r
-\r
- // Empty\r
- public class RdpEmpty : RdpPattern\r
- {\r
- public RdpEmpty () {}\r
- static RdpEmpty ()\r
- {\r
- instance = new RdpEmpty ();\r
- }\r
-\r
- public override bool Nullable {\r
- get { return true; }\r
- }\r
-\r
- static RdpEmpty instance;\r
- public static RdpEmpty Instance {\r
- get { return instance; }\r
- }\r
-\r
- public override RelaxngPatternType PatternType {\r
- get { return RelaxngPatternType.Empty; }\r
- }\r
-\r
- public override RdpContentType ContentType {\r
- get { return RdpContentType.Empty; }\r
- }\r
-\r
- public override void GetLabels (LabelList elements, LabelList attributes)\r
- {\r
- // do nothing\r
- }\r
-\r
- internal override void MarkReachableDefs () \r
- {\r
- // do nothing\r
- }\r
-\r
- internal override void CheckConstraints (bool attribute, bool oneOrMore, bool oneOrMoreGroup, bool oneOrMoreInterleave, bool list, bool dataExcept)\r
- {\r
- if (dataExcept)\r
- throw new RelaxngException ("empty cannot appear under except of a data pattern.");\r
- }\r
-\r
- internal override bool ContainsText()\r
- {\r
- return false;\r
- }\r
- }\r
-\r
- // NotAllowed\r
- public class RdpNotAllowed : RdpPattern\r
- {\r
- public RdpNotAllowed () {}\r
- static RdpNotAllowed ()\r
- {\r
- instance = new RdpNotAllowed ();\r
- }\r
-\r
- static RdpNotAllowed instance;\r
- public static RdpNotAllowed Instance {\r
- get { return instance; }\r
- }\r
-\r
- public override bool Nullable {\r
- get { return false; }\r
- }\r
-\r
- public override RdpPattern ApplyAfter (RdpApplyAfterHandler h)\r
- {\r
- return RdpNotAllowed.Instance;\r
- }\r
-\r
- public override RelaxngPatternType PatternType {\r
- get { return RelaxngPatternType.NotAllowed; }\r
- }\r
-\r
- public override RdpContentType ContentType {\r
- get { return RdpContentType.Empty; }\r
- }\r
-\r
- internal override void MarkReachableDefs () \r
- {\r
- // do nothing\r
- }\r
-\r
- internal override void CheckConstraints (bool attribute, bool oneOrMore, bool oneOrMoreGroup, bool oneOrMoreInterleave, bool list, bool dataExcept)\r
- {\r
- // do nothing\r
- }\r
-\r
- internal override bool ContainsText()\r
- {\r
- return false;\r
- }\r
-\r
- public override void GetLabels (LabelList elements, LabelList attributes)\r
- {\r
- // FIXME: Supposed to clear something here?\r
- }\r
- }\r
-\r
- // Text\r
- public class RdpText : RdpPattern\r
- {\r
- static RdpText instance;\r
- public static RdpText Instance {\r
- get { return instance; }\r
- }\r
-\r
- public RdpText () {}\r
- static RdpText ()\r
- {\r
- instance = new RdpText ();\r
- }\r
-\r
- public override bool Nullable {\r
- get { return true; }\r
- }\r
-\r
- public override RelaxngPatternType PatternType {\r
- get { return RelaxngPatternType.Text; }\r
- }\r
-\r
- public override RdpContentType ContentType {\r
- get { return RdpContentType.Complex; }\r
- }\r
-\r
- public override RdpPattern TextDeriv (string s, XmlReader reader)\r
- {\r
- return this;\r
- }\r
-\r
- internal override void MarkReachableDefs () \r
- {\r
- // do nothing\r
- }\r
-\r
- internal override void CheckConstraints (bool attribute, bool oneOrMore, bool oneOrMoreGroup, bool oneOrMoreInterleave, bool list, bool dataExcept)\r
- {\r
- if (list)\r
- throw new RelaxngException ("text is not allowed under a list.");\r
- if (dataExcept)\r
- throw new RelaxngException ("text is not allowed under except of a list.");\r
- }\r
-\r
- internal override bool ContainsText()\r
- {\r
- return true;\r
- }\r
-\r
- public override void GetLabels (LabelList elements, LabelList attributes)\r
- {\r
- // do nothing\r
- }\r
- }\r
-\r
- // AbstractBinary\r
- public abstract class RdpAbstractBinary : RdpPattern\r
- {\r
- public RdpAbstractBinary (RdpPattern l, RdpPattern r)\r
- {\r
- this.l = l;\r
- this.r = r;\r
- }\r
-\r
- RdpPattern l;\r
- public RdpPattern LValue {\r
- get { return l; }\r
- set { l = value; }\r
- }\r
-\r
- RdpPattern r;\r
- public RdpPattern RValue {\r
- get { return r; }\r
- set { r = value; }\r
- }\r
-\r
- public override RdpContentType ContentType {\r
- get {\r
- if (l.ContentType == RdpContentType.Empty)\r
- return r.ContentType;\r
- if (r.ContentType == RdpContentType.Empty)\r
- return l.ContentType;\r
-\r
- if ((l.ContentType & RdpContentType.Simple) != 0 || ((r.ContentType & RdpContentType.Simple) != 0))\r
- throw new RelaxngException ("The content type of this group is invalid.");\r
- return RdpContentType.Complex;\r
- }\r
- }\r
-\r
- bool expanded;\r
- internal override RdpPattern ExpandRef (Hashtable defs)\r
- {\r
- if (!expanded) {\r
- l = l.ExpandRef (defs);\r
- r = r.ExpandRef (defs);\r
- }\r
- return this;\r
- }\r
-\r
- internal override RdpPattern ReduceEmptyAndNotAllowed (ref bool result, Hashtable visited)\r
- {\r
- if (visited.Contains (this))\r
- return this;\r
- visited.Add (this, this);\r
-\r
- if (LValue.PatternType == RelaxngPatternType.NotAllowed ||\r
- RValue.PatternType == RelaxngPatternType.NotAllowed) {\r
- result = true;\r
- return RdpNotAllowed.Instance;\r
- } else if (LValue.PatternType == RelaxngPatternType.Empty) {\r
- result = true;\r
- return RValue.ReduceEmptyAndNotAllowed (ref result, visited);\r
- } else if (RValue.PatternType == RelaxngPatternType.Empty) {\r
- result = true;\r
- return LValue.ReduceEmptyAndNotAllowed (ref result, visited);\r
- } else {\r
- LValue = LValue.ReduceEmptyAndNotAllowed (ref result, visited);\r
- RValue = RValue.ReduceEmptyAndNotAllowed (ref result, visited);\r
- return this;\r
- }\r
- }\r
-\r
- internal override void MarkReachableDefs () \r
- {\r
- l.MarkReachableDefs ();\r
- r.MarkReachableDefs ();\r
- }\r
-\r
- internal override bool ContainsText()\r
- {\r
- return l.ContainsText () || r.ContainsText ();\r
- }\r
-\r
- internal override void CheckAttributeDuplicates ()\r
- {\r
- LValue.CheckAttributeDuplicates ();\r
- RValue.CheckAttributeDuplicates ();\r
- }\r
-\r
- // 7.3\r
- internal void CheckAttributeDuplicatesCore ()\r
- {\r
- // expecting all items are interned\r
- bool checkAttributes = false;\r
- Hashtable lc = new Hashtable ();\r
- LValue.GetLabels (null, lc);\r
- if (lc.Count == 0)\r
- return;\r
-\r
- Hashtable rc = new Hashtable ();\r
- RValue.GetLabels (null, rc);\r
- if (rc.Count == 0)\r
- return;\r
-\r
- foreach (XmlQualifiedName name in lc.Values)\r
- if (rc.Contains (name))\r
- throw new RelaxngException ("Duplicate attributes inside a group or an interleave is not allowed.");\r
- }\r
- }\r
-\r
- // Choice\r
- public class RdpChoice : RdpAbstractBinary\r
- {\r
- public RdpChoice (RdpPattern l, RdpPattern r) : base (l, r)\r
- {\r
- }\r
-\r
- public override bool Nullable {\r
- get {\r
- if (!nullableComputed) {\r
- isNullable =\r
- LValue.Nullable || RValue.Nullable;\r
- nullableComputed = true;\r
- }\r
- return isNullable;\r
- }\r
- }\r
-\r
- public override RelaxngPatternType PatternType {\r
- get { return RelaxngPatternType.Choice; }\r
- }\r
-\r
- public override RdpContentType ContentType {\r
- get {\r
- if (LValue.ContentType == RdpContentType.Simple ||\r
- RValue.ContentType == RdpContentType.Simple)\r
- return RdpContentType.Simple;\r
- return base.ContentType;\r
- }\r
- }\r
-\r
- public override void GetLabels (LabelList elements, LabelList attributes)\r
- {\r
- LValue.GetLabels (elements, attributes);\r
- RValue.GetLabels (elements, attributes);\r
- }\r
-\r
-\r
- internal override RdpPattern ReduceEmptyAndNotAllowed (ref bool result, Hashtable visited)\r
- {\r
- if (visited.Contains (this))\r
- return this;\r
- visited.Add (this, this);\r
-\r
- if (LValue.PatternType == RelaxngPatternType.NotAllowed &&\r
- RValue.PatternType == RelaxngPatternType.NotAllowed) {\r
- result = true;\r
- return RdpNotAllowed.Instance;\r
- } else if (LValue.PatternType == RelaxngPatternType.NotAllowed) {\r
- result = true;\r
- return RValue.ReduceEmptyAndNotAllowed (ref result, visited);\r
- } else if (RValue.PatternType == RelaxngPatternType.NotAllowed) {\r
- result = true;\r
- return LValue.ReduceEmptyAndNotAllowed (ref result, visited);\r
- } else if (LValue.PatternType == RelaxngPatternType.Empty &&\r
- RValue.PatternType == RelaxngPatternType.Empty) {\r
- result = true;\r
- return RdpEmpty.Instance;\r
- } else if (RValue.PatternType == RelaxngPatternType.Empty) {\r
- result = true;\r
- RValue = LValue.ReduceEmptyAndNotAllowed (ref result, visited);\r
- LValue = RdpEmpty.Instance;\r
- return this;\r
- } else {\r
- LValue = LValue.ReduceEmptyAndNotAllowed (ref result, visited);\r
- RValue = RValue.ReduceEmptyAndNotAllowed (ref result, visited);\r
- return this;\r
- }\r
- }\r
-\r
- public override RdpPattern TextDeriv (string s, XmlReader reader)\r
- {\r
- return LValue.TextDeriv (s, reader).Choice (RValue.TextDeriv (s, reader));\r
- }\r
-\r
- public override RdpPattern ApplyAfter (RdpApplyAfterHandler handler)\r
- {\r
-// return handler (LValue).Choice (handler (RValue));\r
- return LValue.ApplyAfter (handler).Choice (RValue.ApplyAfter (handler));\r
- }\r
-\r
- public override RdpPattern StartTagOpenDeriv (string name, string ns)\r
- {\r
-#if UseStatic\r
- return RdpUtil.Choice (\r
- RdpUtil.StartTagOpenDeriv (LValue, qname),\r
- RdpUtil.StartTagOpenDeriv (RValue, qname));\r
-#else\r
- RdpPattern lDeriv = LValue.StartTagOpenDeriv (name, ns);\r
- return lDeriv.Choice (RValue.StartTagOpenDeriv (name, ns));\r
-#endif\r
- }\r
-\r
- // attDeriv cx (Choice p1 p2) att =\r
- // choice (attDeriv cx p1 att) (attDeriv cx p2 att)\r
- public override RdpPattern AttDeriv (string name, string ns, string value, XmlReader reader)\r
- {\r
- return LValue.AttDeriv (name, ns, value, reader)\r
- .Choice (RValue.AttDeriv (name, ns, value, reader));\r
- }\r
-\r
- // startTagCloseDeriv (Choice p1 p2) =\r
- // choice (startTagCloseDeriv p1) (startTagCloseDeriv p2)\r
- public override RdpPattern StartTagCloseDeriv ()\r
- {\r
- return LValue.StartTagCloseDeriv ()\r
- .Choice (RValue.StartTagCloseDeriv ());\r
- }\r
-\r
- public override RdpPattern EndTagDeriv ()\r
- {\r
- return LValue.EndTagDeriv ().Choice (RValue.EndTagDeriv ());\r
- }\r
-\r
- internal override void CheckConstraints (bool attribute, bool oneOrMore, bool oneOrMoreGroup, bool oneOrMoreInterleave, bool list, bool dataExcept)\r
- {\r
- LValue.CheckConstraints (attribute, oneOrMore, oneOrMoreGroup, oneOrMoreInterleave, list, dataExcept);\r
- RValue.CheckConstraints (attribute, oneOrMore, oneOrMoreGroup, oneOrMoreInterleave, list, dataExcept);\r
- }\r
- }\r
-\r
- // Interleave\r
- public class RdpInterleave : RdpAbstractBinary\r
- {\r
- public RdpInterleave (RdpPattern l, RdpPattern r) : base (l, r)\r
- {\r
- }\r
-\r
- public override bool Nullable {\r
- get {\r
- if (!nullableComputed) {\r
- isNullable =\r
- LValue.Nullable && RValue.Nullable;\r
- nullableComputed = true;\r
- }\r
- return isNullable;\r
- }\r
- }\r
-\r
- public override void GetLabels (LabelList elements, LabelList attributes)\r
- {\r
- LValue.GetLabels (elements, attributes);\r
- RValue.GetLabels (elements, attributes);\r
- }\r
-\r
- internal override RdpPattern ReduceEmptyAndNotAllowed (ref bool result, Hashtable visited)\r
- {\r
- if (visited.Contains (this))\r
- return this;\r
- visited.Add (this, this);\r
-\r
- if (LValue.PatternType == RelaxngPatternType.NotAllowed ||\r
- RValue.PatternType == RelaxngPatternType.NotAllowed) {\r
- result = true;\r
- return RdpNotAllowed.Instance;\r
- } else {\r
- LValue = LValue.ReduceEmptyAndNotAllowed (ref result, visited);\r
- RValue = RValue.ReduceEmptyAndNotAllowed (ref result, visited);\r
- return this;\r
- }\r
- }\r
-\r
- public override RdpPattern TextDeriv (string s, XmlReader reader)\r
- {\r
- return LValue.TextDeriv (s, reader).Interleave (RValue)\r
- .Choice (LValue.Interleave (RValue.TextDeriv (s, reader)));\r
- }\r
-\r
- // => choice (applyAfter (flip interleave p2) (startTagOpenDeriv p1 qn)) (applyAfter (interleave p1) (startTagOpenDeriv p2 qn)\r
- // => p1.startTagOpenDeriv(qn).applyAfter (flip interleave p2).choice (p2.startTagOpenDeriv(qn).applyAfter (interleave p1) )\r
- public override RdpPattern StartTagOpenDeriv (string name, string ns)\r
- {\r
- RdpPattern handledL = LValue.StartTagOpenDeriv (name, ns);\r
- RdpPattern handledR = RValue.StartTagOpenDeriv (name, ns);\r
- RdpFlip flipL = new RdpFlip (new RdpBinaryFunction (RdpUtil.Interleave), RValue);\r
- RdpPattern choiceL = handledL.ApplyAfter (new RdpApplyAfterHandler (flipL.Apply));\r
- RdpPattern choiceR = handledR.ApplyAfter (new RdpApplyAfterHandler (LValue.Interleave));\r
- return choiceL.Choice (choiceR);\r
- }\r
-\r
- // attDeriv cx (Interleave p1 p2) att =\r
- // choice (interleave (attDeriv cx p1 att) p2)\r
- // (interleave p1 (attDeriv cx p2 att))\r
- public override RdpPattern AttDeriv (string name, string ns, string value, XmlReader reader)\r
- {\r
- return LValue.AttDeriv (name, ns, value, reader)\r
- .Interleave (RValue)\r
- .Choice (LValue.Interleave (\r
- RValue.AttDeriv (name, ns, value, reader)));\r
- }\r
-\r
- // startTagCloseDeriv (Interleave p1 p2) =\r
- // interleave (startTagCloseDeriv p1) (startTagCloseDeriv p2)\r
- public override RdpPattern StartTagCloseDeriv ()\r
- {\r
- return LValue.StartTagCloseDeriv ()\r
- .Interleave (RValue.StartTagCloseDeriv ());\r
- }\r
-\r
- /*\r
- // FIXME: This is not specified in James Clark's algorithm, so\r
- // this may raise unstable behaviour!!\r
- // I think this is right but not confident.\r
- \r
- // ... then I reminded to include it.\r
- public override RdpPattern EndTagDeriv ()\r
- {\r
- return LValue.Nullable ? RValue : RdpNotAllowed.Instance;\r
- }\r
- */\r
-\r
- public override RelaxngPatternType PatternType {\r
- get { return RelaxngPatternType.Interleave; }\r
- }\r
-\r
- internal override void CheckConstraints (bool attribute, bool oneOrMore, bool oneOrMoreGroup, bool oneOrMoreInterleave, bool list, bool dataExcept)\r
- {\r
- if (list)\r
- throw new RelaxngException ("interleave is not allowed under a list.");\r
- if (dataExcept)\r
- throw new RelaxngException ("interleave is not allowed under except of a data.");\r
-\r
- // 7.1\r
- LValue.CheckConstraints (attribute, oneOrMore, oneOrMoreGroup, oneOrMore, list, dataExcept);\r
- RValue.CheckConstraints (attribute, oneOrMore, oneOrMoreGroup, oneOrMore, list, dataExcept);\r
-\r
- // 7.4\r
- // TODO: (1) unique name analysis\r
- // (2) text/text prohibited\r
- if (LValue.PatternType == RelaxngPatternType.Text && RValue.PatternType == RelaxngPatternType.Text)\r
- throw new RelaxngException ("Both branches of the interleave contains a text pattern.");\r
- }\r
-\r
- // 7.3\r
- internal override void CheckAttributeDuplicates ()\r
- {\r
- base.CheckAttributeDuplicates ();\r
- CheckAttributeDuplicatesCore ();\r
- }\r
- }\r
-\r
- // Group\r
- public class RdpGroup : RdpAbstractBinary\r
- {\r
- public RdpGroup (RdpPattern l, RdpPattern r) : base (l, r)\r
- {\r
- }\r
-\r
- public override bool Nullable {\r
- get {\r
- if (!nullableComputed) {\r
- isNullable =\r
- LValue.Nullable && RValue.Nullable;\r
- nullableComputed = true;\r
- }\r
- return isNullable;\r
- }\r
- }\r
-\r
- public override void GetLabels (LabelList elements, LabelList attributes)\r
- {\r
- LValue.GetLabels (elements, attributes);\r
- if (LValue.Nullable)\r
- RValue.GetLabels (elements, attributes);\r
- else\r
- RValue.GetLabels (null, attributes);\r
- }\r
-\r
- public override RdpPattern TextDeriv (string s, XmlReader reader)\r
- {\r
- RdpPattern p = LValue.TextDeriv (s, reader).Group (RValue);\r
- return LValue.Nullable ?\r
- p.Choice (RValue.TextDeriv(s, reader)) : p;\r
- }\r
-\r
- // startTagOpenDeriv (Group p1 p2) qn =\r
- // let x = applyAfter (flip group p2) (startTagOpenDeriv p1 qn)\r
- // in if nullable p1 then\r
- // choice x (startTagOpenDeriv p2 qn)\r
- // else\r
- // x\r
- public override RdpPattern StartTagOpenDeriv (string name, string ns)\r
- {\r
- RdpPattern handled = LValue.StartTagOpenDeriv (name, ns);\r
- RdpFlip f = new RdpFlip (new RdpBinaryFunction (RdpUtil.Group), RValue);\r
- RdpPattern x = handled.ApplyAfter (new RdpApplyAfterHandler (f.Apply));\r
- if (LValue.Nullable)\r
- return x.Choice (RValue.StartTagOpenDeriv (name, ns));\r
- else\r
- return x;\r
- }\r
-\r
- // attDeriv cx (Group p1 p2) att =\r
- // choice (group (attDeriv cx p1 att) p2)\r
- // (group p1 (attDeriv cx p2 att))\r
- public override RdpPattern AttDeriv (string name, string ns, string value, XmlReader reader)\r
- {\r
- return LValue.AttDeriv (name, ns, value, reader).Group (RValue)\r
- .Choice (LValue.Group (\r
- RValue.AttDeriv (name, ns, value, reader)));\r
- }\r
-\r
- // startTagCloseDeriv (Group p1 p2) =\r
- // group (startTagCloseDeriv p1) (startTagCloseDeriv p2)\r
- public override RdpPattern StartTagCloseDeriv ()\r
- {\r
- return LValue.StartTagCloseDeriv ()\r
- .Group (RValue.StartTagCloseDeriv ());\r
- }\r
-\r
- public override RelaxngPatternType PatternType {\r
- get { return RelaxngPatternType.Group; }\r
- }\r
-\r
- internal override void CheckConstraints (bool attribute, bool oneOrMore, bool oneOrMoreGroup, bool oneOrMoreInterleave, bool list, bool dataExcept)\r
- {\r
- if (dataExcept)\r
- throw new RelaxngException ("interleave is not allowed under except of a data.");\r
-\r
- LValue.CheckConstraints (attribute, oneOrMore, oneOrMore, oneOrMoreInterleave, list, dataExcept);\r
- RValue.CheckConstraints (attribute, oneOrMore, oneOrMore, oneOrMoreInterleave, list, dataExcept);\r
- }\r
-\r
- // 7.3\r
- internal override void CheckAttributeDuplicates ()\r
- {\r
- base.CheckAttributeDuplicates ();\r
- CheckAttributeDuplicatesCore ();\r
- }\r
- }\r
-\r
- public abstract class RdpAbstractSingleContent : RdpPattern\r
- {\r
- RdpPattern child;\r
- bool isExpanded;\r
-\r
- internal override RdpPattern ExpandRef (Hashtable defs)\r
- {\r
- if (!isExpanded)\r
- child = child.ExpandRef (defs);\r
- return this;\r
- }\r
-\r
- public RdpAbstractSingleContent (RdpPattern p)\r
- {\r
- this.child = p;\r
- }\r
-\r
- public RdpPattern Child {\r
- get { return child; }\r
- set { child = value; }\r
- }\r
-\r
- internal override void MarkReachableDefs () \r
- {\r
- child.MarkReachableDefs ();\r
- }\r
-\r
- internal override bool ContainsText()\r
- {\r
- return child.ContainsText ();\r
- }\r
-\r
- internal override void CheckAttributeDuplicates ()\r
- {\r
- child.CheckAttributeDuplicates ();\r
- }\r
- }\r
-\r
- // OneOrMore\r
- public class RdpOneOrMore : RdpAbstractSingleContent\r
- {\r
- public RdpOneOrMore (RdpPattern p) : base (p)\r
- {\r
- }\r
-\r
- public override RelaxngPatternType PatternType {\r
- get { return RelaxngPatternType.OneOrMore; }\r
- }\r
-\r
- public override RdpContentType ContentType {\r
- get {\r
- if (Child.ContentType == RdpContentType.Simple)\r
- throw new RelaxngException ("Invalid content type was found.");\r
- return Child.ContentType;\r
- }\r
- }\r
-\r
- public override bool Nullable {\r
- get { return Child.Nullable; }\r
- }\r
-\r
- public override void GetLabels (LabelList elements, LabelList attributes)\r
- {\r
- Child.GetLabels (elements, attributes);\r
- }\r
-\r
- internal override RdpPattern ReduceEmptyAndNotAllowed (ref bool result, Hashtable visited)\r
- {\r
- if (visited.Contains (this))\r
- return this;\r
- visited.Add (this, this);\r
-\r
- if (Child.PatternType == RelaxngPatternType.NotAllowed) {\r
- result = true;\r
- return RdpNotAllowed.Instance;\r
- } else if (Child.PatternType == RelaxngPatternType.Empty)\r
- return RdpEmpty.Instance;\r
- else {\r
- Child = Child.ReduceEmptyAndNotAllowed (ref result, visited);\r
- return this;\r
- }\r
- }\r
-\r
- public override RdpPattern TextDeriv (string s, XmlReader reader)\r
- {\r
- return Child.TextDeriv (s, reader).Group (Choice (RdpEmpty.Instance));\r
- }\r
-\r
- // attDeriv cx (OneOrMore p) att =\r
- // group (attDeriv cx p att) (choice (OneOrMore p) Empty)\r
- public override RdpPattern AttDeriv (string name, string ns, string value, XmlReader reader)\r
- {\r
-#if UseStatic\r
- return RdpUtil.Group (\r
- RdpUtil.AttDeriv (ctx, children, att),\r
- RdpUtil.Choice (RdpUtil.OneOrMore (children), RdpEmpty.Instance));\r
-#else\r
- return Child.AttDeriv (name, ns, value, reader)\r
- .Group (Choice (RdpEmpty.Instance));\r
-#endif\r
- }\r
-\r
- // startTagOpenDeriv (OneOrMore p) qn =\r
- // applyAfter (flip group (choice (OneOrMore p) Empty))\r
- // (startTagOpenDeriv p qn)\r
- public override RdpPattern StartTagOpenDeriv (string name, string ns)\r
- {\r
- RdpPattern rest = RdpEmpty.Instance.Choice (Child.OneOrMore ());\r
- RdpPattern handled = Child.StartTagOpenDeriv (name, ns);\r
- RdpFlip f = new RdpFlip (new RdpBinaryFunction (RdpUtil.Group), rest);\r
- return handled.ApplyAfter (new RdpApplyAfterHandler (f.Apply));\r
- }\r
-\r
- // startTagCloseDeriv (OneOrMore p) =\r
- // oneOrMore (startTagCloseDeriv p)\r
- public override RdpPattern StartTagCloseDeriv ()\r
- {\r
-#if UseStatic\r
- return RdpUtil.OneOrMore (\r
- RdpUtil.StartTagCloseDeriv (children));\r
-#else\r
- return Child.StartTagCloseDeriv ().OneOrMore ();\r
-#endif\r
- }\r
-\r
- internal override void CheckConstraints (bool attribute, bool oneOrMore, bool oneOrMoreGroup, bool oneOrMoreInterleave, bool list, bool dataExcept)\r
- {\r
- if (dataExcept)\r
- throw new RelaxngException ("oneOrMore is not allowed under except of a data.");\r
- this.Child.CheckConstraints (attribute, true, oneOrMoreGroup, oneOrMoreInterleave, list, dataExcept);\r
- }\r
- }\r
-\r
- // List\r
- public class RdpList : RdpAbstractSingleContent\r
- {\r
- public RdpList (RdpPattern p) : base (p)\r
- {\r
- }\r
-\r
- internal override RdpPattern ReduceEmptyAndNotAllowed (ref bool result, Hashtable visited)\r
- {\r
- if (visited.Contains (this))\r
- return this;\r
- visited.Add (this, this);\r
-\r
- if (Child.PatternType == RelaxngPatternType.NotAllowed) {\r
- result = true;\r
- return RdpNotAllowed.Instance;\r
- } else {\r
- Child = Child.ReduceEmptyAndNotAllowed (ref result, visited);\r
- return this;\r
- }\r
- }\r
-\r
-/*\r
- // This is not written in James Clark's derivative algorithm\r
- // ( http://www.thaiopensource.com/relaxng/derivative.html ),\r
- // but it looks required.\r
- public override bool Nullable {\r
- get { return this.Child.Nullable; }\r
- }\r
- \r
- // ... but it also causes different error:\r
- // <list><group><data .../><data .../></group></list>\r
-*/\r
- public override bool Nullable {\r
- get { return false; }\r
- }\r
-\r
- public override RelaxngPatternType PatternType {\r
- get { return RelaxngPatternType.List; }\r
- }\r
-\r
- public override RdpContentType ContentType {\r
- get { return RdpContentType.Simple; }\r
- }\r
-\r
- public override void GetLabels (LabelList elements, LabelList attributes)\r
- {\r
- Child.GetLabels (elements, attributes);\r
- }\r
-\r
- public override RdpPattern TextDeriv (string s, XmlReader reader)\r
- {\r
- RdpPattern p = Child.ListDeriv (Util.NormalizeWhitespace (s).Split (RdpUtil.WhitespaceChars), 0, reader); \r
- if (p.Nullable)\r
- return RdpEmpty.Instance;\r
- else\r
- return RdpNotAllowed.Instance;\r
- }\r
-\r
- internal override void CheckConstraints (bool attribute, bool oneOrMore, bool oneOrMoreGroup, bool oneOrMoreInterleave, bool list, bool dataExcept)\r
- {\r
- if (list)\r
- throw new RelaxngException ("list is not allowed uner another list.");\r
- if (dataExcept)\r
- throw new RelaxngException ("list is not allowed under except of a data.");\r
- this.Child.CheckConstraints (attribute, oneOrMore, oneOrMoreGroup, oneOrMoreInterleave, true, dataExcept);\r
- }\r
- }\r
-\r
- // Data\r
- public class RdpData : RdpPattern\r
- {\r
- public RdpData (RdpDatatype dt)\r
- {\r
- this.dt = dt;\r
- }\r
-\r
- RdpDatatype dt;\r
- public RdpDatatype Datatype {\r
- get { return dt; }\r
- }\r
-\r
- // This is not written in James Clark's derivative algorithm\r
- // ( http://www.thaiopensource.com/relaxng/derivative.html ),\r
- // but it looks required.\r
- public override bool Nullable {\r
- get {\r
- if (dt.NamespaceURI.Length == 0)\r
- return true;\r
- return false; \r
- }\r
- }\r
-\r
- public override RelaxngPatternType PatternType {\r
- get { return RelaxngPatternType.Data; }\r
- }\r
-\r
- public override RdpContentType ContentType {\r
- get { return RdpContentType.Simple; }\r
- }\r
-\r
- public override void GetLabels (LabelList elements, LabelList attributes)\r
- {\r
- // do nothing.\r
- }\r
-\r
- public override RdpPattern TextDeriv (string s, XmlReader reader)\r
- {\r
- if (dt.IsAllowed (s, reader))\r
- return RdpEmpty.Instance;\r
- else\r
- return RdpNotAllowed.Instance;\r
- }\r
-\r
- internal override void MarkReachableDefs () \r
- {\r
- // do nothing\r
- }\r
-\r
- internal override void CheckConstraints (bool attribute, bool oneOrMore, bool oneOrMoreGroup, bool oneOrMoreInterleave, bool list, bool dataExcept)\r
- {\r
- // do nothing\r
- }\r
-\r
- internal override bool ContainsText()\r
- {\r
- return false;\r
- }\r
- }\r
-\r
- // DataExcept\r
- public class RdpDataExcept : RdpData\r
- {\r
- public RdpDataExcept (RdpDatatype dt, RdpPattern except)\r
- : base (dt)\r
- {\r
- this.except = except;\r
- }\r
-\r
- RdpPattern except;\r
- public RdpPattern Except {\r
- get { return except; }\r
- set { except = value; }\r
- }\r
-\r
- public override RelaxngPatternType PatternType {\r
- get { return RelaxngPatternType.DataExcept; }\r
- }\r
-\r
- public override RdpContentType ContentType {\r
- get {\r
- RdpContentType c = except.ContentType; // conformance required for except pattern.\r
- return RdpContentType.Simple;\r
- }\r
- }\r
-\r
- internal override RdpPattern ReduceEmptyAndNotAllowed (ref bool result, Hashtable visited)\r
- {\r
- if (visited.Contains (this))\r
- return this;\r
- visited.Add (this, this);\r
-\r
- if (except.PatternType == RelaxngPatternType.NotAllowed) {\r
- result = true;\r
- return new RdpData (this.Datatype);\r
- } else {\r
- except = except.ReduceEmptyAndNotAllowed (ref result, visited);\r
- return this;\r
- }\r
- }\r
-\r
- public override RdpPattern TextDeriv (string s, XmlReader reader)\r
- {\r
- if (Datatype.IsAllowed (s, reader) && !except.TextDeriv (s, reader).Nullable)\r
- return RdpEmpty.Instance;\r
- else\r
- return RdpNotAllowed.Instance;\r
- }\r
-\r
- internal override void CheckConstraints (bool attribute, bool oneOrMore, bool oneOrMoreGroup, bool oneOrMoreInterleave, bool list, bool dataExcept)\r
- {\r
- this.except.CheckConstraints (attribute, oneOrMore, oneOrMoreGroup, oneOrMoreInterleave, list, true);\r
- }\r
-\r
- internal override bool ContainsText()\r
- {\r
- return except.ContainsText ();\r
- }\r
- }\r
-\r
- // Value\r
- public class RdpValue : RdpPattern\r
- {\r
- public RdpValue (RdpDatatype dt, string value)\r
- {\r
- this.dt = dt;\r
- this.value = value;\r
- }\r
-\r
- RdpDatatype dt;\r
- public RdpDatatype Datatype {\r
- get { return dt; }\r
- }\r
-\r
- string value;\r
- public string Value {\r
- get { return value; }\r
- }\r
-\r
- // This is not written in James Clark's derivative algorithm\r
- // ( http://www.thaiopensource.com/relaxng/derivative.html ),\r
- // but it looks required.\r
- public override bool Nullable {\r
- get {\r
- if (dt.NamespaceURI.Length == 0 && value.Length == 0)\r
- return true;\r
- return false; \r
- }\r
- }\r
-\r
- public override RelaxngPatternType PatternType {\r
- get { return RelaxngPatternType.Value; }\r
- }\r
-\r
- public override RdpContentType ContentType {\r
- get { return RdpContentType.Simple; }\r
- }\r
-\r
- public override void GetLabels (LabelList elements, LabelList attributes)\r
- {\r
- // do nothing\r
- }\r
-\r
- public override RdpPattern TextDeriv (string s, XmlReader reader)\r
- {\r
- if (dt.IsTypeEqual (value, s, reader))\r
- return RdpEmpty.Instance;\r
- else\r
- return RdpNotAllowed.Instance;\r
- }\r
-\r
- internal override void MarkReachableDefs () \r
- {\r
- // do nothing\r
- }\r
-\r
- internal override void CheckConstraints (bool attribute, bool oneOrMore, bool oneOrMoreGroup, bool oneOrMoreInterleave, bool list, bool dataExcept) \r
- {\r
- // nothing to be checked\r
- }\r
-\r
- internal override bool ContainsText()\r
- {\r
- return false;\r
- }\r
- }\r
-\r
- // Attribute\r
- public class RdpAttribute : RdpPattern\r
- {\r
- public RdpAttribute (RdpNameClass nameClass, RdpPattern p)\r
- {\r
- this.nameClass = nameClass;\r
- this.children = p;\r
- }\r
-\r
- RdpNameClass nameClass;\r
- public RdpNameClass NameClass {\r
- get { return nameClass; }\r
- }\r
-\r
- RdpPattern children;\r
- public RdpPattern Children {\r
- get { return children; }\r
- set { children = value; }\r
- }\r
-\r
- public override bool Nullable {\r
- get { return false; }\r
- }\r
-\r
- public override RelaxngPatternType PatternType {\r
- get { return RelaxngPatternType.Attribute; }\r
- }\r
-\r
- public override RdpContentType ContentType {\r
- get { return RdpContentType.Empty; }\r
- }\r
-\r
- public override void GetLabels (LabelList elements, LabelList attributes)\r
- {\r
- AddNameLabel (attributes, NameClass);\r
- }\r
-\r
- bool isExpanded;\r
- internal override RdpPattern ExpandRef (Hashtable defs)\r
- {\r
- if (!isExpanded) {\r
- isExpanded = true;\r
- children = children.ExpandRef (defs);\r
- }\r
- return this;\r
- }\r
-\r
- internal override RdpPattern ReduceEmptyAndNotAllowed (ref bool result, Hashtable visited)\r
- {\r
- if (visited.Contains (this))\r
- return this;\r
- visited.Add (this, this);\r
-\r
- if (children.PatternType == RelaxngPatternType.NotAllowed) {\r
- result = true;\r
- return RdpNotAllowed.Instance;\r
- } else {\r
- children = children.ReduceEmptyAndNotAllowed (ref result, visited);\r
- return this;\r
- }\r
- }\r
-\r
- // attDeriv cx (Attribute nc p) (AttributeNode qn s) =\r
- // if contains nc qn && valueMatch cx p s then Empty else NotAllowed\r
- public override RdpPattern AttDeriv (string name, string ns, string value, XmlReader reader)\r
- {\r
- // If value is null, then does not check ValueMatch.\r
-#if UseStatic\r
- if (RdpUtil.Contains (this.nameClass, att.QName)\r
- && (value == null || RdpUtil.ValueMatch (ctx, this.children, att.Value)))\r
- return RdpEmpty.Instance;\r
- else\r
- return RdpNotAllowed.Instance;\r
-#else\r
- if (nameClass.Contains (name, ns) &&\r
- (value == null || children.ValueMatch (value, reader)))\r
- return RdpEmpty.Instance;\r
- else\r
- return RdpNotAllowed.Instance;\r
-#endif\r
- }\r
-\r
- // startTagCloseDeriv (Attribute _ _) = NotAllowed\r
- public override RdpPattern StartTagCloseDeriv ()\r
- {\r
- return RdpNotAllowed.Instance;\r
- }\r
-\r
- internal override void MarkReachableDefs () \r
- {\r
- children.MarkReachableDefs ();\r
- }\r
-\r
- internal override void CheckConstraints (bool attribute, bool oneOrMore, bool oneOrMoreGroup, bool oneOrMoreInterleave, bool list, bool dataExcept) \r
- {\r
- if (attribute || oneOrMoreGroup || oneOrMoreInterleave || list || dataExcept)\r
- throw new RelaxngException ("Not allowed attribute occurence was specified in the pattern.");\r
- this.Children.CheckConstraints (true, oneOrMore, false, false, false, false);\r
- }\r
-\r
- internal override bool ContainsText()\r
- {\r
- return children.ContainsText ();\r
- }\r
- }\r
-\r
- // Element\r
- public class RdpElement : RdpPattern\r
- {\r
- public RdpElement (RdpNameClass nameClass, RdpPattern p)\r
- {\r
- this.nameClass = nameClass;\r
- this.children = p;\r
- }\r
-\r
- RdpNameClass nameClass;\r
- public RdpNameClass NameClass {\r
- get { return nameClass; }\r
- }\r
-\r
- RdpPattern children;\r
- public RdpPattern Children {\r
- get { return children; }\r
- set { children = value; }\r
- }\r
-\r
- public override bool Nullable {\r
- get { return false; }\r
- }\r
-\r
- public override RelaxngPatternType PatternType {\r
- get { return RelaxngPatternType.Element; }\r
- }\r
-\r
- bool contentTypeCheckDone;\r
- public override RdpContentType ContentType {\r
- get {\r
- if (!contentTypeCheckDone) {\r
- contentTypeCheckDone = true;\r
- RdpContentType ct = children.ContentType; // conformance required.\r
- }\r
- return RdpContentType.Complex;\r
- }\r
- }\r
-\r
- public override void GetLabels (LabelList elements, LabelList attributes)\r
- {\r
- AddNameLabel (elements, NameClass);\r
- }\r
-\r
-\r
- bool isExpanded;\r
- short expanding; // FIXME: It is totally not required, but there is\r
- // some bugs in simplification and without it it causes infinite loop.\r
- internal override RdpPattern ExpandRef (Hashtable defs)\r
- {\r
- if (!isExpanded) {\r
- isExpanded = true;\r
- if (expanding == 100)\r
- throw new RelaxngException (String.Format ("Invalid recursion was found. Name is {0}", nameClass));\r
- expanding++;\r
- children = children.ExpandRef (defs);\r
- expanding--;\r
- }\r
- return this;\r
- }\r
-\r
- internal override RdpPattern ReduceEmptyAndNotAllowed (ref bool result, Hashtable visited)\r
- {\r
- if (visited.Contains (this))\r
- return this;\r
- visited.Add (this, this);\r
-\r
- children = children.ReduceEmptyAndNotAllowed (ref result, visited);\r
- return this;\r
- }\r
-\r
- public override RdpPattern StartTagOpenDeriv (string name, string ns)\r
- {\r
-#if UseStatic\r
- if (RdpUtil.Contains (this.nameClass, qname))\r
- return RdpUtil.After (this.Children, RdpEmpty.Instance);\r
- else\r
- return RdpNotAllowed.Instance;\r
-#else\r
- return nameClass.Contains (name, ns) ?\r
- children.After (RdpEmpty.Instance) :\r
- RdpNotAllowed.Instance;\r
-#endif\r
- }\r
-\r
- internal override void MarkReachableDefs () \r
- {\r
- children.MarkReachableDefs ();\r
- }\r
-\r
- bool constraintsChecked;\r
- internal override void CheckConstraints (bool attribute, bool oneOrMore, bool oneOrMoreGroup, bool oneOrMoreInterleave, bool list, bool dataExcept) \r
- {\r
- if (constraintsChecked)\r
- return;\r
- constraintsChecked = true;\r
- if (attribute || list || dataExcept)\r
- throw new RelaxngException ("Not allowed element occurence was specified in the pattern.");\r
- this.Children.CheckConstraints (false, oneOrMore, oneOrMoreGroup, oneOrMoreInterleave, false, false);\r
- }\r
-\r
- internal override bool ContainsText()\r
- {\r
- return children.ContainsText ();\r
- }\r
-\r
- internal override void CheckAttributeDuplicates ()\r
- {\r
- children.CheckAttributeDuplicates ();\r
- }\r
- }\r
-\r
- // After\r
- public class RdpAfter : RdpAbstractBinary\r
- {\r
- public RdpAfter (RdpPattern l, RdpPattern r) : base (l, r)\r
- {\r
- }\r
-\r
- public override bool Nullable {\r
- get { return false; }\r
- }\r
-\r
- public override void GetLabels (LabelList elements, LabelList attributes)\r
- {\r
- LValue.GetLabels (elements, attributes);\r
- }\r
-\r
- public override RdpPattern TextDeriv (string s, XmlReader reader)\r
- {\r
- return LValue.TextDeriv (s, reader).After (RValue);\r
- }\r
-\r
- // startTagOpenDeriv (After p1 p2) qn =\r
- // applyAfter (flip after p2) (startTagOpenDeriv p1 qn)\r
- public override RdpPattern StartTagOpenDeriv (string name, string ns)\r
- {\r
- RdpPattern handled = LValue.StartTagOpenDeriv (name, ns);\r
- RdpFlip f = new RdpFlip (new RdpBinaryFunction (RdpUtil.After), RValue);\r
- return handled.ApplyAfter (new RdpApplyAfterHandler (\r
- f.Apply));\r
- }\r
-\r
- public override RdpPattern ApplyAfter (RdpApplyAfterHandler handler)\r
- {\r
- return LValue.After (handler (RValue));\r
- }\r
-\r
- // attDeriv cx (After p1 p2) att =\r
- // after (attDeriv cx p1 att) p2\r
- public override RdpPattern AttDeriv (string name, string ns, string value, XmlReader reader)\r
- {\r
- return LValue.AttDeriv (name, ns, value, reader).After (RValue);\r
- }\r
-\r
- public override RdpPattern StartTagCloseDeriv ()\r
- {\r
- return LValue.StartTagCloseDeriv ().After (RValue);\r
- }\r
-\r
- public override RdpPattern EndTagDeriv ()\r
- {\r
- return LValue.Nullable ? RValue : RdpNotAllowed.Instance;\r
- }\r
-\r
- public override RelaxngPatternType PatternType {\r
- get { return RelaxngPatternType.After; }\r
- }\r
-\r
- internal override void MarkReachableDefs () \r
- {\r
- throw new InvalidOperationException ();\r
- }\r
-\r
- internal override void CheckConstraints (bool attribute, bool oneOrMore, bool oneOrMoreGroup, bool oneOrMoreInterleave, bool list, bool dataExcept) \r
- {\r
- throw new InvalidOperationException ();\r
- }\r
-\r
- internal override bool ContainsText ()\r
- {\r
- throw new InvalidOperationException ();\r
- }\r
- }\r
-}\r
-\r
+
+using System;
+using System.Collections;
+using System.Xml;
+using Commons.Xml.Relaxng;
+
+using LabelList = System.Collections.Hashtable;
+
+
+namespace Commons.Xml.Relaxng.Derivative
+{
+ public delegate RdpPattern RdpApplyAfterHandler (RdpPattern p);
+
+ // abstract Pattern. Note that in README the classes in this namespace
+ // is explicitly written as not for public use (and hidden in monodoc
+ // for now).
+ public abstract class RdpPattern
+ {
+ internal bool nullableComputed;
+ internal bool isNullable;
+ Hashtable patternPool;
+
+ internal string debug ()
+ {
+ return RdpUtil.DebugRdpPattern (this, new Hashtable ());
+ }
+
+ public abstract RelaxngPatternType PatternType { get; }
+
+ public abstract RdpContentType ContentType { get; }
+
+ private Hashtable setupTable (Type type, RdpPattern p)
+ {
+ if (patternPool == null) // could be null for RdpElement etc.
+ patternPool = new Hashtable ();
+
+ Hashtable typePool = (Hashtable) patternPool [type];
+ if (typePool == null) {
+ typePool = new Hashtable ();
+ patternPool [type] = typePool;
+ }
+ Hashtable pTable = (Hashtable) typePool [p];
+ if (pTable == null) {
+ pTable = new Hashtable ();
+ typePool [p] = pTable;
+ }
+ return pTable;
+ }
+
+ internal RdpFlip MakeFlip (RdpBinaryFunction func, RdpPattern p)
+ {
+ if (patternPool == null) // could be null for RdpElement etc.
+ patternPool = new Hashtable ();
+
+ // Though this method takes function argument, all
+ // p1 callers have different pattern types, so we don't
+ // have to distinguish tables by func.
+
+ Hashtable table = patternPool [func] as Hashtable;
+ if (table == null) {
+ table = new Hashtable ();
+ patternPool [func] = table;
+ }
+ RdpFlip f = table [p] as RdpFlip;
+ if (f != null)
+ return f;
+ f = new RdpFlip (func, p);
+ table [p] = f;
+ return f;
+ }
+
+ public RdpChoice MakeChoiceLeaf (RdpPattern p)
+ {
+ if (patternPool == null) // could be null for RdpElement etc.
+ patternPool = new Hashtable ();
+ Hashtable leaves = (Hashtable) patternPool [typeof (RdpEmpty)];
+ if (leaves == null) {
+ leaves = new Hashtable ();
+ patternPool [typeof (RdpEmpty)] = leaves;
+ }
+ RdpChoice leaf = leaves [p] as RdpChoice;
+ if (leaf == null) {
+ leaf = new RdpChoice (RdpEmpty.Instance, p);
+ leaf.setInternTable (patternPool);
+ leaves [p] = leaf;
+ }
+ return leaf;
+ }
+
+ public RdpPattern MakeChoice (RdpPattern p1, RdpPattern p2)
+ {
+ if (p1.PatternType == RelaxngPatternType.NotAllowed)
+ 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);
+ if (p2.PatternType == RelaxngPatternType.Empty)
+ return MakeChoiceLeaf (p1);
+
+ if (p1.GetHashCode () > p2.GetHashCode ()) {
+ RdpPattern tmp = p1;
+ p1 = p2;
+ p2 = tmp;
+ }
+
+ Hashtable p1Table = setupTable (typeof (RdpChoice), p1);
+ if (p1Table [p2] == null) {
+ RdpChoice c = new RdpChoice (p1, p2);
+ c.setInternTable (this.patternPool);
+ p1Table [p2] = c;
+ }
+ return (RdpChoice) p1Table [p2];
+ }
+
+ public RdpPattern MakeGroup (RdpPattern p1, RdpPattern p2)
+ {
+ if (p1.PatternType == RelaxngPatternType.Empty)
+ return p2;
+
+ Hashtable p1Table = setupTable (typeof (RdpGroup), p1);
+ if (p1Table [p2] == null) {
+ RdpGroup g = new RdpGroup (p1, p2);
+ g.setInternTable (this.patternPool);
+ p1Table [p2] = g;
+ }
+ return (RdpGroup) p1Table [p2];
+ }
+
+ public RdpInterleave MakeInterleave (RdpPattern p1, RdpPattern p2)
+ {
+ if (p1.GetHashCode () > p2.GetHashCode ()) {
+ RdpPattern tmp = p1;
+ p1 = p2;
+ p2 = tmp;
+ }
+
+ Hashtable p1Table = setupTable (typeof (RdpInterleave), p1);
+ if (p1Table [p2] == null) {
+ RdpInterleave i = new RdpInterleave (p1, p2);
+ i.setInternTable (this.patternPool);
+ p1Table [p2] = i;
+ }
+ return (RdpInterleave) p1Table [p2];
+ }
+
+ public RdpAfter MakeAfter (RdpPattern p1, RdpPattern p2)
+ {
+ Hashtable p1Table = setupTable (typeof (RdpAfter), p1);
+ if (p1Table [p2] == null) {
+ RdpAfter a = new RdpAfter (p1, p2);
+ a.setInternTable (this.patternPool);
+ p1Table [p2] = a;
+ }
+ return (RdpAfter) p1Table [p2];
+ }
+
+ public RdpOneOrMore MakeOneOrMore (RdpPattern p)
+ {
+ if (patternPool == null) // could be null for RdpElement etc.
+ patternPool = new Hashtable ();
+
+ Hashtable pTable = (Hashtable) patternPool [typeof (RdpOneOrMore)];
+ if (pTable == null) {
+ pTable = new Hashtable ();
+ patternPool [typeof (RdpOneOrMore)] = pTable;
+ }
+ if (pTable [p] == null) {
+ RdpOneOrMore oom = new RdpOneOrMore (p);
+ oom.setInternTable (patternPool);
+ pTable [p] = oom;
+ }
+ return (RdpOneOrMore) pTable [p];
+ }
+
+ internal void setInternTable (Hashtable ht)
+ {
+ if (this.patternPool != null)
+ return;
+ this.patternPool = ht;
+
+ Hashtable pt = ht [GetType ()] as Hashtable;
+ if (pt == null) {
+ pt = new Hashtable ();
+ ht [GetType ()] = pt;
+ }
+
+ RdpAbstractSingleContent single =
+ this as RdpAbstractSingleContent;
+ if (single != null) {
+ if (pt [single.Child] == null) {
+ pt [single.Child] = this;
+ single.Child.setInternTable (ht);
+ }
+ return;
+ }
+
+ RdpAbstractBinary binary =
+ this as RdpAbstractBinary;
+ if (binary != null) {
+ Hashtable lTable = setupTable (GetType (), binary.LValue);
+ if (lTable [binary.RValue] == null) {
+ lTable [binary.RValue] = this;
+ binary.LValue.setInternTable (ht);
+ binary.RValue.setInternTable (ht);
+ }
+ return;
+ }
+
+ // For rest patterns, only check recursively, without pooling.
+ RdpAttribute attr = this as RdpAttribute;
+ if (attr != null) {
+ attr.Children.setInternTable (ht);
+ return;
+ }
+ RdpElement el = this as RdpElement;
+ if (el != null) {
+ el.Children.setInternTable (ht);
+ return;
+ }
+ RdpDataExcept dex= this as RdpDataExcept;
+ if (dex != null) {
+ dex.Except.setInternTable (ht);
+ return;
+ }
+
+ switch (PatternType) {
+ case RelaxngPatternType.Empty:
+ case RelaxngPatternType.NotAllowed:
+ case RelaxngPatternType.Text:
+ case RelaxngPatternType.Data:
+ case RelaxngPatternType.Value:
+ return;
+ }
+
+#if REPLACE_IN_ADVANCE
+ throw new InvalidOperationException ();
+#endif
+ }
+
+ internal abstract void MarkReachableDefs ();
+
+ internal abstract void CheckConstraints (bool attribute, bool oneOrMore, bool oneOrMoreGroup, bool oneOrMoreInterleave, bool list, bool dataExcept);
+
+ // This method is to detect text pattern inside interleave child.
+ internal abstract bool ContainsText ();
+
+ internal virtual RdpPattern ExpandRef (Hashtable defs)
+ {
+ return this;
+ }
+
+ internal virtual RdpPattern ReduceEmptyAndNotAllowed (ref bool result, Hashtable visited)
+ {
+ return this;
+ }
+
+ public abstract bool Nullable { get; }
+
+ internal virtual bool IsTextValueDependent {
+ get { return false; }
+ }
+
+ internal virtual bool IsContextDependent {
+ get { return false; }
+ }
+
+ // fills QName collection
+ public void GetLabels (LabelList elements, LabelList attributes)
+ {
+ GetLabels (elements, attributes, false);
+ }
+
+ public abstract void GetLabels (LabelList elements, LabelList attributes, bool collectNameClass);
+
+ internal void AddNameLabel (LabelList names, RdpNameClass nc)
+ {
+ RdpName name = nc as RdpName;
+ if (name != null) {
+ XmlQualifiedName qname = new XmlQualifiedName (
+ name.LocalName, name.NamespaceURI);
+ names [qname] = qname;
+ return;
+ }
+ RdpNameClassChoice choice = nc as RdpNameClassChoice;
+ if (choice != null) {
+ AddNameLabel (names, choice.LValue);
+ AddNameLabel (names, choice.RValue);
+ return;
+ }
+ // For NsName and AnyName, do nothing.
+ }
+
+ #region Derivative
+ public virtual RdpPattern TextDeriv (string s, XmlReader reader)
+ {
+ 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;
+ }
+
+ internal virtual RdpPattern TextOnlyDeriv (MemoizationStore store)
+ {
+ return this;
+ }
+
+ internal virtual RdpPattern MixedTextDeriv ()
+ {
+ return RdpNotAllowed.Instance;
+ }
+
+ internal virtual RdpPattern MixedTextDeriv (MemoizationStore memo)
+ {
+ return RdpNotAllowed.Instance;
+ }
+
+ public RdpPattern ListDeriv (string [] list, int index, XmlReader reader)
+ {
+ return listDerivInternal (list, 0, reader);
+ }
+
+ private RdpPattern listDerivInternal (string [] list, int start, XmlReader reader)
+ {
+ if (list.Length <= start)
+ return this;
+ else if (list [start].Length == 0)
+ return listDerivInternal (list, start + 1, reader);
+ else
+ return this.TextDeriv (list [start].Trim (RdpUtil.WhitespaceChars), reader).listDerivInternal (list, start + 1, reader);
+ }
+
+ // Choice(this, p)
+ public virtual RdpPattern Choice (RdpPattern p)
+ {
+ if (p is RdpNotAllowed)
+ return this;
+ else if (this is RdpNotAllowed)
+ return p;
+ else
+ return MakeChoice (this, p);
+ }
+
+ // Group(this, p)
+ public virtual RdpPattern Group (RdpPattern p)
+ {
+ if (p is RdpNotAllowed || this is RdpNotAllowed)
+ return RdpNotAllowed.Instance;
+ else if (p is RdpEmpty)
+ return this;
+ else if (this is RdpEmpty)
+ return p;
+ else
+ return MakeGroup (this, p);
+ }
+
+ // Interleave(this, p)
+ public virtual RdpPattern Interleave (RdpPattern p)
+ {
+ if (p is RdpNotAllowed || this is RdpNotAllowed)
+ return RdpNotAllowed.Instance;
+ else if (p is RdpEmpty)
+ return this;
+ else if (this is RdpEmpty)
+ return p;
+ else
+ return MakeInterleave (this, p);
+ }
+
+ // After(this, p)
+ public virtual RdpPattern After (RdpPattern p)
+ {
+ if (this is RdpNotAllowed || p is RdpNotAllowed)
+ return RdpNotAllowed.Instance;
+ else
+ return MakeAfter (this, p);
+ }
+
+
+ // applyAfter((f, p1=this), p2)
+ public virtual RdpPattern ApplyAfter (RdpApplyAfterHandler h)
+ {
+ throw new Exception ("INTERNAL ERROR: should not happen. This is " + this);
+ }
+
+ // startTagOpenDeriv (this, qname)
+ // startTagOpenDeriv _ qn = NotAllowed (default)
+ public virtual RdpPattern StartTagOpenDeriv (string name, string ns)
+ {
+ return RdpNotAllowed.Instance;
+ }
+
+ internal virtual RdpPattern StartTagOpenDeriv (string name, string ns, MemoizationStore memo)
+ {
+ return StartTagOpenDeriv (name, ns);
+ }
+
+ // attDeriv(ctx, this, att)
+ // attDeriv _ _ _ = NotAllowed
+ public virtual RdpPattern AttDeriv (string name, string ns, string value, XmlReader reader)
+ {
+ return RdpNotAllowed.Instance;
+ }
+
+ public virtual RdpPattern StartAttDeriv (string name, string ns)
+ {
+ return RdpNotAllowed.Instance;
+ }
+
+ internal virtual RdpPattern StartAttDeriv (string name, string ns, MemoizationStore memo)
+ {
+ return StartAttDeriv (name, ns);
+ }
+
+ public virtual RdpPattern EndAttDeriv ()
+ {
+ return RdpNotAllowed.Instance;
+ }
+
+ internal virtual RdpPattern EndAttDeriv (MemoizationStore memo)
+ {
+ return EndAttDeriv ();
+ }
+
+ public bool ValueMatch (string s, XmlReader reader)
+ {
+ return Nullable && Util.IsWhitespace (s) ||
+ TextDeriv (s, reader).Nullable;
+ }
+
+ public virtual RdpPattern StartTagCloseDeriv ()
+ {
+ return this;
+ }
+
+ internal virtual RdpPattern StartTagCloseDeriv (MemoizationStore memo)
+ {
+ return StartTagCloseDeriv ();
+ }
+
+ public RdpPattern OneOrMore ()
+ {
+ if (PatternType == RelaxngPatternType.NotAllowed)
+ return RdpNotAllowed.Instance;
+ else
+ return MakeOneOrMore (this);
+ }
+
+ public virtual RdpPattern EndTagDeriv ()
+ {
+ return RdpNotAllowed.Instance;
+ }
+
+ internal virtual RdpPattern EndTagDeriv (MemoizationStore memo)
+ {
+ return EndTagDeriv ();
+ }
+ #endregion
+ }
+
+ // Empty
+ public class RdpEmpty : RdpPattern
+ {
+ public RdpEmpty () {}
+ static RdpEmpty ()
+ {
+ instance = new RdpEmpty ();
+ }
+
+ public override bool Nullable {
+ get { return true; }
+ }
+
+ internal override bool IsTextValueDependent {
+ get { return false; }
+ }
+
+ internal override bool IsContextDependent {
+ get { return false; }
+ }
+
+ static RdpEmpty instance;
+ public static RdpEmpty Instance {
+ get { return instance; }
+ }
+
+ public override RelaxngPatternType PatternType {
+ get { return RelaxngPatternType.Empty; }
+ }
+
+ public override RdpContentType ContentType {
+ get { return RdpContentType.Empty; }
+ }
+
+ public override void GetLabels (LabelList elements, LabelList attributes, bool collectNameClass)
+ {
+ // do nothing
+ }
+
+ internal override void MarkReachableDefs ()
+ {
+ // do nothing
+ }
+
+ internal override void CheckConstraints (bool attribute, bool oneOrMore, bool oneOrMoreGroup, bool oneOrMoreInterleave, bool list, bool dataExcept)
+ {
+ if (dataExcept)
+ throw new RelaxngException ("empty cannot appear under except of a data pattern.");
+ }
+
+ internal override bool ContainsText()
+ {
+ return false;
+ }
+ }
+
+ // NotAllowed
+ public class RdpNotAllowed : RdpPattern
+ {
+ public RdpNotAllowed () {}
+ static RdpNotAllowed ()
+ {
+ instance = new RdpNotAllowed ();
+ }
+
+ static RdpNotAllowed instance;
+ public static RdpNotAllowed Instance {
+ get { return instance; }
+ }
+
+ public override bool Nullable {
+ get { return false; }
+ }
+
+ internal override bool IsTextValueDependent {
+ get { return false; }
+ }
+
+ internal override bool IsContextDependent {
+ get { return false; }
+ }
+
+ public override RdpPattern ApplyAfter (RdpApplyAfterHandler h)
+ {
+ return RdpNotAllowed.Instance;
+ }
+
+ public override RelaxngPatternType PatternType {
+ get { return RelaxngPatternType.NotAllowed; }
+ }
+
+ public override RdpContentType ContentType {
+ get { return RdpContentType.Empty; }
+ }
+
+ internal override void MarkReachableDefs ()
+ {
+ // do nothing
+ }
+
+ internal override void CheckConstraints (bool attribute, bool oneOrMore, bool oneOrMoreGroup, bool oneOrMoreInterleave, bool list, bool dataExcept)
+ {
+ // do nothing
+ }
+
+ internal override bool ContainsText()
+ {
+ return false;
+ }
+
+ public override void GetLabels (LabelList elements, LabelList attributes, bool collectNameClass)
+ {
+ // FIXME: Supposed to clear something here?
+ }
+ }
+
+ // Text
+ public class RdpText : RdpPattern
+ {
+ static RdpText instance;
+ public static RdpText Instance {
+ get { return instance; }
+ }
+
+ public RdpText () {}
+ static RdpText ()
+ {
+ instance = new RdpText ();
+ }
+
+ public override bool Nullable {
+ get { return true; }
+ }
+
+ internal override bool IsTextValueDependent {
+ get { return false; }
+ }
+
+ internal override bool IsContextDependent {
+ get { return false; }
+ }
+
+ public override RelaxngPatternType PatternType {
+ get { return RelaxngPatternType.Text; }
+ }
+
+ public override RdpContentType ContentType {
+ get { return RdpContentType.Complex; }
+ }
+
+ public override RdpPattern TextDeriv (string s, XmlReader reader)
+ {
+ return this;
+ }
+
+ internal override RdpPattern EmptyTextDeriv (MemoizationStore memo)
+ {
+ return this;
+ }
+
+ internal override RdpPattern MixedTextDeriv ()
+ {
+ return this;
+ }
+
+ internal override RdpPattern MixedTextDeriv (MemoizationStore memo)
+ {
+ return this;
+ }
+
+ internal override void MarkReachableDefs ()
+ {
+ // do nothing
+ }
+
+ internal override void CheckConstraints (bool attribute, bool oneOrMore, bool oneOrMoreGroup, bool oneOrMoreInterleave, bool list, bool dataExcept)
+ {
+ if (list)
+ throw new RelaxngException ("text is not allowed under a list.");
+ if (dataExcept)
+ throw new RelaxngException ("text is not allowed under except of a list.");
+ }
+
+ internal override bool ContainsText()
+ {
+ return true;
+ }
+
+ public override void GetLabels (LabelList elements, LabelList attributes, bool collectNameClass)
+ {
+ // do nothing
+ }
+ }
+
+ // AbstractBinary
+ public abstract class RdpAbstractBinary : RdpPattern
+ {
+ public RdpAbstractBinary (RdpPattern l, RdpPattern r)
+ {
+ this.l = l;
+ this.r = r;
+ }
+
+ RdpPattern l;
+ public RdpPattern LValue {
+ get { return l; }
+ set { l = value; }
+ }
+
+ RdpPattern r;
+ public RdpPattern RValue {
+ get { return r; }
+ set { r = value; }
+ }
+
+ RdpContentType computedContentType = RdpContentType.Invalid;
+ public override RdpContentType ContentType {
+ get {
+ if (computedContentType == RdpContentType.Invalid) {
+ if (l.ContentType == RdpContentType.Empty)
+ computedContentType = r.ContentType;
+ else if (r.ContentType == RdpContentType.Empty)
+ computedContentType = l.ContentType;
+ else if ((l.ContentType & RdpContentType.Simple) != 0 || ((r.ContentType & RdpContentType.Simple) != 0))
+ throw new RelaxngException ("The content type of this group is invalid.");
+ else
+ computedContentType = RdpContentType.Complex;
+ }
+ return computedContentType;
+ }
+ }
+
+ bool expanded;
+ internal override RdpPattern ExpandRef (Hashtable defs)
+ {
+ if (!expanded) {
+ l = l.ExpandRef (defs);
+ r = r.ExpandRef (defs);
+ }
+ return this;
+ }
+
+ internal override RdpPattern ReduceEmptyAndNotAllowed (ref bool result, Hashtable visited)
+ {
+ if (visited.Contains (this))
+ return this;
+ visited.Add (this, this);
+
+ if (LValue.PatternType == RelaxngPatternType.NotAllowed ||
+ RValue.PatternType == RelaxngPatternType.NotAllowed) {
+ result = true;
+ return RdpNotAllowed.Instance;
+ } else if (LValue.PatternType == RelaxngPatternType.Empty) {
+ result = true;
+ return RValue.ReduceEmptyAndNotAllowed (ref result, visited);
+ } else if (RValue.PatternType == RelaxngPatternType.Empty) {
+ result = true;
+ return LValue.ReduceEmptyAndNotAllowed (ref result, visited);
+ } else {
+ LValue = LValue.ReduceEmptyAndNotAllowed (ref result, visited);
+ RValue = RValue.ReduceEmptyAndNotAllowed (ref result, visited);
+ return this;
+ }
+ }
+
+ internal override void MarkReachableDefs ()
+ {
+ l.MarkReachableDefs ();
+ r.MarkReachableDefs ();
+ }
+
+ internal override bool ContainsText()
+ {
+ return l.ContainsText () || r.ContainsText ();
+ }
+
+ // 7.3 (group/interleave attribute names) and
+ // part of 7.4 (interleave element names)
+ // FIXME: Actually it should be done against the correct
+ // simplified grammar, expanding all refs.
+ internal void CheckNameOverlap (bool checkElements)
+ {
+ if (RdpUtil.NamesOverlap (LValue, RValue, checkElements))
+ throw new RelaxngException ("Duplicate attributes inside a group or an interleave is not allowed.");
+ return;
+ }
+ }
+
+ // Choice
+ public class RdpChoice : RdpAbstractBinary
+ {
+ public RdpChoice (RdpPattern l, RdpPattern r) : base (l, r)
+ {
+ }
+
+ public override bool Nullable {
+ get {
+ if (!nullableComputed) {
+ isNullable =
+ LValue.Nullable || RValue.Nullable;
+ nullableComputed = true;
+ }
+ return isNullable;
+ }
+ }
+
+ bool isTextValueDependentComputed;
+ bool isTextValueDependent;
+
+ internal override bool IsTextValueDependent {
+ get {
+ if (!isTextValueDependentComputed) {
+ isTextValueDependent = LValue.IsTextValueDependent || RValue.IsTextValueDependent;
+ isTextValueDependentComputed = true;
+ }
+ return isTextValueDependent;
+ }
+ }
+
+ 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; }
+ }
+
+ RdpContentType computedContentType = RdpContentType.Invalid;
+ public override RdpContentType ContentType {
+ get {
+ if (computedContentType == RdpContentType.Invalid) {
+ if (LValue.ContentType == RdpContentType.Simple ||
+ RValue.ContentType == RdpContentType.Simple)
+ computedContentType = RdpContentType.Simple;
+ else
+ computedContentType = base.ContentType;
+ }
+ return computedContentType;
+ }
+ }
+
+ public override void GetLabels (LabelList elements, LabelList attributes, bool collectNameClass)
+ {
+ LValue.GetLabels (elements, attributes, collectNameClass);
+ RValue.GetLabels (elements, attributes, collectNameClass);
+ }
+
+
+ internal override RdpPattern ReduceEmptyAndNotAllowed (ref bool result, Hashtable visited)
+ {
+ if (visited.Contains (this))
+ return this;
+ visited.Add (this, this);
+
+ if (LValue.PatternType == RelaxngPatternType.NotAllowed &&
+ RValue.PatternType == RelaxngPatternType.NotAllowed) {
+ result = true;
+ return RdpNotAllowed.Instance;
+ } else if (LValue.PatternType == RelaxngPatternType.NotAllowed) {
+ result = true;
+ return RValue.ReduceEmptyAndNotAllowed (ref result, visited);
+ } else if (RValue.PatternType == RelaxngPatternType.NotAllowed) {
+ result = true;
+ return LValue.ReduceEmptyAndNotAllowed (ref result, visited);
+ } else if (LValue.PatternType == RelaxngPatternType.Empty &&
+ RValue.PatternType == RelaxngPatternType.Empty) {
+ result = true;
+ return RdpEmpty.Instance;
+ } else if (RValue.PatternType == RelaxngPatternType.Empty) {
+ result = true;
+ RValue = LValue.ReduceEmptyAndNotAllowed (ref result, visited);
+ LValue = RdpEmpty.Instance;
+ return this;
+ } else {
+ LValue = LValue.ReduceEmptyAndNotAllowed (ref result, visited);
+ RValue = RValue.ReduceEmptyAndNotAllowed (ref result, visited);
+ return this;
+ }
+ }
+
+ public override RdpPattern TextDeriv (string s, XmlReader reader)
+ {
+ 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 (
+ RValue.TextOnlyDeriv ());
+ }
+
+ internal override RdpPattern TextOnlyDeriv (MemoizationStore memo)
+ {
+ return memo.TextOnlyDeriv (LValue).Choice (
+ memo.TextOnlyDeriv (RValue));
+ }
+
+ internal override RdpPattern MixedTextDeriv ()
+ {
+ return LValue.MixedTextDeriv ().Choice (
+ RValue.MixedTextDeriv ());
+ }
+
+ internal override RdpPattern MixedTextDeriv (MemoizationStore memo)
+ {
+ return memo.MixedTextDeriv (LValue).Choice (
+ memo.MixedTextDeriv (RValue));
+ }
+
+ public override RdpPattern ApplyAfter (RdpApplyAfterHandler handler)
+ {
+// return handler (LValue).Choice (handler (RValue));
+ return LValue.ApplyAfter (handler).Choice (RValue.ApplyAfter (handler));
+ }
+
+ public override RdpPattern StartTagOpenDeriv (string name, string ns)
+ {
+#if UseStatic
+ return RdpUtil.Choice (
+ RdpUtil.StartTagOpenDeriv (LValue, qname),
+ RdpUtil.StartTagOpenDeriv (RValue, qname));
+#else
+ RdpPattern lDeriv = LValue.StartTagOpenDeriv (name, ns);
+ return lDeriv.Choice (RValue.StartTagOpenDeriv (name, ns));
+#endif
+ }
+
+ internal override RdpPattern StartTagOpenDeriv (string name, string ns, MemoizationStore memo)
+ {
+ RdpPattern lDeriv = memo.StartTagOpenDeriv (LValue, name, ns);
+ return lDeriv.Choice (memo.StartTagOpenDeriv (RValue, name, ns));
+ }
+
+ // attDeriv cx (Choice p1 p2) att =
+ // choice (attDeriv cx p1 att) (attDeriv cx p2 att)
+ public override RdpPattern AttDeriv (string name, string ns, string value, XmlReader reader)
+ {
+ return LValue.AttDeriv (name, ns, value, reader)
+ .Choice (RValue.AttDeriv (name, ns, value, reader));
+ }
+
+ public override RdpPattern StartAttDeriv (string name, string ns)
+ {
+ RdpPattern lDeriv = LValue.StartAttDeriv (name, ns);
+ return lDeriv.Choice (RValue.StartAttDeriv (name, ns));
+ }
+
+ internal override RdpPattern StartAttDeriv (string name, string ns, MemoizationStore memo)
+ {
+ return memo.StartAttDeriv (LValue, name, ns)
+ .Choice (memo.StartAttDeriv (RValue, name, ns));
+ }
+
+ public override RdpPattern EndAttDeriv ()
+ {
+ return LValue.EndAttDeriv ().Choice (RValue.EndAttDeriv ());
+ }
+
+ internal override RdpPattern EndAttDeriv (MemoizationStore memo)
+ {
+ return memo.EndAttDeriv (LValue).Choice (memo.EndAttDeriv (RValue));
+ }
+
+ // startTagCloseDeriv (Choice p1 p2) =
+ // choice (startTagCloseDeriv p1) (startTagCloseDeriv p2)
+ public override RdpPattern StartTagCloseDeriv ()
+ {
+ return LValue.StartTagCloseDeriv ()
+ .Choice (RValue.StartTagCloseDeriv ());
+ }
+
+ internal override RdpPattern StartTagCloseDeriv (MemoizationStore memo)
+ {
+ return memo.StartTagCloseDeriv (LValue)
+ .Choice (memo.StartTagCloseDeriv (RValue));
+ }
+
+ public override RdpPattern EndTagDeriv ()
+ {
+ return LValue.EndTagDeriv ().Choice (RValue.EndTagDeriv ());
+ }
+
+ internal override RdpPattern EndTagDeriv (MemoizationStore memo)
+ {
+ return memo.EndTagDeriv (LValue).Choice (memo.EndTagDeriv (RValue));
+ }
+
+ internal override void CheckConstraints (bool attribute, bool oneOrMore, bool oneOrMoreGroup, bool oneOrMoreInterleave, bool list, bool dataExcept)
+ {
+ LValue.CheckConstraints (attribute, oneOrMore, oneOrMoreGroup, oneOrMoreInterleave, list, dataExcept);
+ RValue.CheckConstraints (attribute, oneOrMore, oneOrMoreGroup, oneOrMoreInterleave, list, dataExcept);
+ }
+ }
+
+ // Interleave
+ public class RdpInterleave : RdpAbstractBinary
+ {
+ public RdpInterleave (RdpPattern l, RdpPattern r) : base (l, r)
+ {
+ }
+
+ public override bool Nullable {
+ get {
+ if (!nullableComputed) {
+ isNullable =
+ LValue.Nullable && RValue.Nullable;
+ nullableComputed = true;
+ }
+ return isNullable;
+ }
+ }
+
+ internal override bool IsTextValueDependent {
+ 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);
+ RValue.GetLabels (elements, attributes, collectNameClass);
+ }
+
+ internal override RdpPattern ReduceEmptyAndNotAllowed (ref bool result, Hashtable visited)
+ {
+ if (visited.Contains (this))
+ return this;
+ visited.Add (this, this);
+
+ if (LValue.PatternType == RelaxngPatternType.NotAllowed ||
+ RValue.PatternType == RelaxngPatternType.NotAllowed) {
+ result = true;
+ return RdpNotAllowed.Instance;
+ } else {
+ LValue = LValue.ReduceEmptyAndNotAllowed (ref result, visited);
+ RValue = RValue.ReduceEmptyAndNotAllowed (ref result, visited);
+ return this;
+ }
+ }
+
+ public override RdpPattern TextDeriv (string s, XmlReader reader)
+ {
+ return LValue.TextDeriv (s, reader).Interleave (RValue)
+ .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 (
+ RValue.TextOnlyDeriv ());
+ }
+
+ internal override RdpPattern TextOnlyDeriv (MemoizationStore memo)
+ {
+ return memo.TextOnlyDeriv (LValue).Interleave (
+ memo.TextOnlyDeriv (RValue));
+ }
+
+ internal override RdpPattern MixedTextDeriv ()
+ {
+ return LValue.MixedTextDeriv ().Interleave (RValue).Choice (
+ LValue.Interleave (RValue.MixedTextDeriv ()));
+ }
+
+ internal override RdpPattern MixedTextDeriv (MemoizationStore memo)
+ {
+ return memo.MixedTextDeriv (LValue).Interleave (RValue).Choice (
+ LValue.Interleave (memo.MixedTextDeriv (RValue)));
+ }
+
+ // => choice (applyAfter (flip interleave p2) (startTagOpenDeriv p1 qn)) (applyAfter (interleave p1) (startTagOpenDeriv p2 qn)
+ // => p1.startTagOpenDeriv(qn).applyAfter (flip interleave p2).choice (p2.startTagOpenDeriv(qn).applyAfter (interleave p1) )
+ public override RdpPattern StartTagOpenDeriv (string name, string ns)
+ {
+ RdpPattern handledL = LValue.StartTagOpenDeriv (name, ns);
+ RdpPattern handledR = RValue.StartTagOpenDeriv (name, ns);
+ RdpFlip flipL = MakeFlip (RdpUtil.InterleaveFunction, RValue);
+ RdpPattern choiceL = handledL.ApplyAfter (new RdpApplyAfterHandler (flipL.Apply));
+ RdpPattern choiceR = handledR.ApplyAfter (new RdpApplyAfterHandler (LValue.Interleave));
+ return choiceL.Choice (choiceR);
+ }
+
+ internal override RdpPattern StartTagOpenDeriv (string name, string ns, MemoizationStore memo)
+ {
+ RdpPattern handledL = memo.StartTagOpenDeriv (LValue, name, ns);
+ RdpPattern handledR = memo.StartTagOpenDeriv (RValue, name, ns);
+ RdpFlip flipL = MakeFlip (RdpUtil.InterleaveFunction, RValue);
+ RdpPattern choiceL = handledL.ApplyAfter (new RdpApplyAfterHandler (flipL.Apply));
+ RdpPattern choiceR = handledR.ApplyAfter (new RdpApplyAfterHandler (LValue.Interleave));
+ return choiceL.Choice (choiceR);
+ }
+
+ // attDeriv cx (Interleave p1 p2) att =
+ // choice (interleave (attDeriv cx p1 att) p2)
+ // (interleave p1 (attDeriv cx p2 att))
+ public override RdpPattern AttDeriv (string name, string ns, string value, XmlReader reader)
+ {
+ return LValue.AttDeriv (name, ns, value, reader)
+ .Interleave (RValue)
+ .Choice (LValue.Interleave (
+ RValue.AttDeriv (name, ns, value, reader)));
+ }
+
+ public override RdpPattern StartAttDeriv (string name, string ns)
+ {
+ RdpPattern handledL = LValue.StartAttDeriv (name, ns);
+ RdpPattern handledR = RValue.StartAttDeriv (name, ns);
+ RdpFlip flipL = MakeFlip (RdpUtil.InterleaveFunction, RValue);
+ RdpPattern choiceL = handledL.ApplyAfter (new RdpApplyAfterHandler (flipL.Apply));
+ RdpPattern choiceR = handledR.ApplyAfter (new RdpApplyAfterHandler (LValue.Interleave));
+ return choiceL.Choice (choiceR);
+ }
+
+ internal override RdpPattern StartAttDeriv (string name, string ns, MemoizationStore memo)
+ {
+ RdpPattern handledL = memo.StartAttDeriv (LValue, name, ns);
+ RdpPattern handledR = memo.StartAttDeriv (RValue, name, ns);
+ RdpFlip flipL = MakeFlip (RdpUtil.InterleaveFunction, RValue);
+ RdpPattern choiceL = handledL.ApplyAfter (new RdpApplyAfterHandler (flipL.Apply));
+ RdpPattern choiceR = handledR.ApplyAfter (new RdpApplyAfterHandler (LValue.Interleave));
+ return choiceL.Choice (choiceR);
+ }
+
+ // startTagCloseDeriv (Interleave p1 p2) =
+ // interleave (startTagCloseDeriv p1) (startTagCloseDeriv p2)
+ public override RdpPattern StartTagCloseDeriv ()
+ {
+ return LValue.StartTagCloseDeriv ()
+ .Interleave (RValue.StartTagCloseDeriv ());
+ }
+
+ internal override RdpPattern StartTagCloseDeriv (MemoizationStore memo)
+ {
+ return memo.StartTagCloseDeriv (LValue)
+ .Interleave (memo.StartTagCloseDeriv (RValue));
+ }
+
+ public override RelaxngPatternType PatternType {
+ get { return RelaxngPatternType.Interleave; }
+ }
+
+ internal override void CheckConstraints (bool attribute, bool oneOrMore, bool oneOrMoreGroup, bool oneOrMoreInterleave, bool list, bool dataExcept)
+ {
+ if (list)
+ throw new RelaxngException ("interleave is not allowed under a list.");
+ if (dataExcept)
+ throw new RelaxngException ("interleave is not allowed under except of a data.");
+
+ // 7.1
+ LValue.CheckConstraints (attribute, oneOrMore, oneOrMoreGroup, oneOrMore, list, dataExcept);
+ RValue.CheckConstraints (attribute, oneOrMore, oneOrMoreGroup, oneOrMore, list, dataExcept);
+
+ // unique name analysis - 7.3 and part of 7.4
+ CheckNameOverlap (true);
+
+ // (2) text/text prohibited
+ if (LValue.ContainsText () && RValue.ContainsText ())
+ throw new RelaxngException ("Both branches of the interleave contains a text pattern.");
+ }
+ }
+
+ // Group
+ public class RdpGroup : RdpAbstractBinary
+ {
+ public RdpGroup (RdpPattern l, RdpPattern r) : base (l, r)
+ {
+ }
+
+ public override bool Nullable {
+ get {
+ if (!nullableComputed) {
+ isNullable =
+ LValue.Nullable && RValue.Nullable;
+ nullableComputed = true;
+ }
+ return isNullable;
+ }
+ }
+
+ internal override bool IsTextValueDependent {
+ 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);
+ if (LValue.Nullable)
+ RValue.GetLabels (elements, attributes, collectNameClass);
+ else
+ RValue.GetLabels (null, attributes, collectNameClass);
+ }
+
+ public override RdpPattern TextDeriv (string s, XmlReader reader)
+ {
+ 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 ()
+ {
+ RdpPattern p = LValue.TextOnlyDeriv ();
+ return p.PatternType == RelaxngPatternType.NotAllowed ?
+ p : p.Group (RValue.TextOnlyDeriv ());
+ }
+
+ internal override RdpPattern TextOnlyDeriv (MemoizationStore memo)
+ {
+ RdpPattern p = memo.TextOnlyDeriv (LValue);
+ return p.PatternType == RelaxngPatternType.NotAllowed ?
+ p : p.Group (memo.TextOnlyDeriv (RValue));
+ }
+
+ internal override RdpPattern MixedTextDeriv ()
+ {
+ RdpPattern p = LValue.MixedTextDeriv ().Group (RValue);
+ return LValue.Nullable ?
+ p.Choice (RValue.MixedTextDeriv ()) : p;
+ }
+
+ internal override RdpPattern MixedTextDeriv (MemoizationStore memo)
+ {
+ RdpPattern p = memo.MixedTextDeriv (LValue).Group (RValue);
+ return LValue.Nullable ?
+ p.Choice (memo.MixedTextDeriv (RValue)) : p;
+ }
+
+ // startTagOpenDeriv (Group p1 p2) qn =
+ // let x = applyAfter (flip group p2) (startTagOpenDeriv p1 qn)
+ // in if nullable p1 then
+ // choice x (startTagOpenDeriv p2 qn)
+ // else
+ // x
+ public override RdpPattern StartTagOpenDeriv (string name, string ns)
+ {
+ RdpPattern handled = LValue.StartTagOpenDeriv (name, ns);
+ RdpFlip f = MakeFlip (RdpUtil.GroupFunction, RValue);
+ RdpPattern x = handled.ApplyAfter (new RdpApplyAfterHandler (f.Apply));
+ if (LValue.Nullable)
+ return x.Choice (RValue.StartTagOpenDeriv (name, ns));
+ else
+ return x;
+ }
+
+ internal override RdpPattern StartTagOpenDeriv (string name, string ns, MemoizationStore memo)
+ {
+ RdpPattern handled = memo.StartTagOpenDeriv (LValue, name, ns);
+ RdpFlip f = MakeFlip (RdpUtil.GroupFunction, RValue);
+ RdpPattern x = handled.ApplyAfter (new RdpApplyAfterHandler (f.Apply));
+ if (LValue.Nullable)
+ return x.Choice (memo.StartTagOpenDeriv (RValue, name, ns));
+ else
+ return x;
+ }
+
+ // attDeriv cx (Group p1 p2) att =
+ // choice (group (attDeriv cx p1 att) p2)
+ // (group p1 (attDeriv cx p2 att))
+ public override RdpPattern AttDeriv (string name, string ns, string value, XmlReader reader)
+ {
+ return LValue.AttDeriv (name, ns, value, reader).Group (RValue)
+ .Choice (LValue.Group (
+ RValue.AttDeriv (name, ns, value, reader)));
+ }
+
+ // startAttDeriv (group p1 p2) == startAttDeriv (interleave p1 p2)
+ public override RdpPattern StartAttDeriv (string name, string ns)
+ {
+ RdpPattern handledL = LValue.StartAttDeriv (name, ns);
+ RdpPattern handledR = RValue.StartAttDeriv (name, ns);
+ RdpFlip flipL = MakeFlip (RdpUtil.GroupFunction, RValue);
+ RdpPattern choiceL = handledL.ApplyAfter (new RdpApplyAfterHandler (flipL.Apply));
+ RdpPattern choiceR = handledR.ApplyAfter (new RdpApplyAfterHandler (LValue.Group));
+ return choiceL.Choice (choiceR);
+ }
+
+ internal override RdpPattern StartAttDeriv (string name, string ns, MemoizationStore memo)
+ {
+ RdpPattern handledL = memo.StartAttDeriv (LValue, name, ns);
+ RdpPattern handledR = memo.StartAttDeriv (RValue, name, ns);
+ RdpFlip flipL = MakeFlip (RdpUtil.GroupFunction, RValue);
+ RdpPattern choiceL = handledL.ApplyAfter (new RdpApplyAfterHandler (flipL.Apply));
+ RdpPattern choiceR = handledR.ApplyAfter (new RdpApplyAfterHandler (LValue.Group));
+ return choiceL.Choice (choiceR);
+ }
+
+ // startTagCloseDeriv (Group p1 p2) =
+ // group (startTagCloseDeriv p1) (startTagCloseDeriv p2)
+ public override RdpPattern StartTagCloseDeriv ()
+ {
+ RdpPattern p = LValue.StartTagCloseDeriv ();
+ return p.PatternType == RelaxngPatternType.NotAllowed ?
+ p : p.Group (RValue.StartTagCloseDeriv ());
+ }
+
+ internal override RdpPattern StartTagCloseDeriv (MemoizationStore memo)
+ {
+ RdpPattern p = memo.StartTagCloseDeriv (LValue);
+ return p.PatternType == RelaxngPatternType.NotAllowed ?
+ p : p.Group (memo.StartTagCloseDeriv (RValue));
+ }
+
+ public override RelaxngPatternType PatternType {
+ get { return RelaxngPatternType.Group; }
+ }
+
+ internal override void CheckConstraints (bool attribute, bool oneOrMore, bool oneOrMoreGroup, bool oneOrMoreInterleave, bool list, bool dataExcept)
+ {
+ if (dataExcept)
+ throw new RelaxngException ("interleave is not allowed under except of a data.");
+
+ LValue.CheckConstraints (attribute, oneOrMore, oneOrMore, oneOrMoreInterleave, list, dataExcept);
+ RValue.CheckConstraints (attribute, oneOrMore, oneOrMore, oneOrMoreInterleave, list, dataExcept);
+
+ // 7.3
+ CheckNameOverlap (false);
+ }
+ }
+
+ public abstract class RdpAbstractSingleContent : RdpPattern
+ {
+ RdpPattern child;
+ bool isExpanded;
+
+ internal override RdpPattern ExpandRef (Hashtable defs)
+ {
+ if (!isExpanded)
+ child = child.ExpandRef (defs);
+ return this;
+ }
+
+ public RdpAbstractSingleContent (RdpPattern p)
+ {
+ this.child = p;
+ }
+
+ public RdpPattern Child {
+ get { return child; }
+ set { child = value; }
+ }
+
+ internal override void MarkReachableDefs ()
+ {
+ child.MarkReachableDefs ();
+ }
+
+ internal override bool ContainsText()
+ {
+ return child.ContainsText ();
+ }
+ }
+
+ // OneOrMore
+ public class RdpOneOrMore : RdpAbstractSingleContent
+ {
+ public RdpOneOrMore (RdpPattern p) : base (p)
+ {
+ }
+
+ public override RelaxngPatternType PatternType {
+ get { return RelaxngPatternType.OneOrMore; }
+ }
+
+ public override RdpContentType ContentType {
+ get {
+ if (Child.ContentType == RdpContentType.Simple)
+ throw new RelaxngException ("Invalid content type was found.");
+ return Child.ContentType;
+ }
+ }
+
+ public override bool Nullable {
+ get { return Child.Nullable; }
+ }
+
+ internal override bool IsTextValueDependent {
+ 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);
+ }
+
+ internal override RdpPattern ReduceEmptyAndNotAllowed (ref bool result, Hashtable visited)
+ {
+ if (visited.Contains (this))
+ return this;
+ visited.Add (this, this);
+
+ if (Child.PatternType == RelaxngPatternType.NotAllowed) {
+ result = true;
+ return RdpNotAllowed.Instance;
+ } else if (Child.PatternType == RelaxngPatternType.Empty)
+ return RdpEmpty.Instance;
+ else {
+ Child = Child.ReduceEmptyAndNotAllowed (ref result, visited);
+ return this;
+ }
+ }
+
+ public override RdpPattern TextDeriv (string s, XmlReader reader)
+ {
+ 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 ()
+ {
+ return Child.TextOnlyDeriv ().OneOrMore ();
+ }
+
+ internal override RdpPattern TextOnlyDeriv (MemoizationStore memo)
+ {
+ return memo.TextOnlyDeriv (Child).OneOrMore ();
+ }
+
+ internal override RdpPattern MixedTextDeriv ()
+ {
+ RdpPattern p = Child.MixedTextDeriv ();
+ return p.PatternType == RelaxngPatternType.NotAllowed ?
+ p : p.Group (this.Choice (RdpEmpty.Instance));
+ }
+
+ internal override RdpPattern MixedTextDeriv (MemoizationStore memo)
+ {
+ 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)
+ {
+ RdpPattern p = Child.AttDeriv (name, ns, value, reader);
+ return p.PatternType == RelaxngPatternType.NotAllowed ?
+ p : p.Group (Choice (RdpEmpty.Instance));
+ }
+
+ // startTagOpenDeriv (OneOrMore p) qn =
+ // applyAfter (flip group (choice (OneOrMore p) Empty))
+ // (startTagOpenDeriv p qn)
+ public override RdpPattern StartTagOpenDeriv (string name, string ns)
+ {
+ RdpPattern rest = RdpEmpty.Instance.Choice (Child.OneOrMore ());
+ RdpPattern handled = Child.StartTagOpenDeriv (name, ns);
+ RdpFlip f = MakeFlip (RdpUtil.GroupFunction, rest);
+ return handled.ApplyAfter (new RdpApplyAfterHandler (f.Apply));
+ }
+
+ internal override RdpPattern StartTagOpenDeriv (string name, string ns, MemoizationStore memo)
+ {
+ RdpPattern rest = RdpEmpty.Instance.Choice (Child.OneOrMore ());
+ RdpPattern handled = memo.StartTagOpenDeriv (Child, name, ns);
+ RdpFlip f = MakeFlip (RdpUtil.GroupFunction, rest);
+ return handled.ApplyAfter (new RdpApplyAfterHandler (f.Apply));
+ }
+
+ public override RdpPattern StartAttDeriv (string name, string ns)
+ {
+ RdpPattern rest = RdpEmpty.Instance.Choice (Child.OneOrMore ());
+ RdpPattern handled = Child.StartAttDeriv (name, ns);
+ RdpFlip f = MakeFlip (RdpUtil.GroupFunction, rest);
+ return handled.ApplyAfter (new RdpApplyAfterHandler (f.Apply));
+ }
+
+ internal override RdpPattern StartAttDeriv (string name, string ns, MemoizationStore memo)
+ {
+ RdpPattern rest = RdpEmpty.Instance.Choice (Child.OneOrMore ());
+ RdpPattern handled = memo.StartAttDeriv (Child, name, ns);
+ RdpFlip f = MakeFlip (RdpUtil.GroupFunction, rest);
+ return handled.ApplyAfter (new RdpApplyAfterHandler (f.Apply));
+ }
+
+ // startTagCloseDeriv (OneOrMore p) =
+ // oneOrMore (startTagCloseDeriv p)
+ public override RdpPattern StartTagCloseDeriv ()
+ {
+#if UseStatic
+ return RdpUtil.OneOrMore (
+ RdpUtil.StartTagCloseDeriv (children));
+#else
+ return Child.StartTagCloseDeriv ().OneOrMore ();
+#endif
+ }
+
+ internal override RdpPattern StartTagCloseDeriv (MemoizationStore memo)
+ {
+ return memo.StartTagCloseDeriv (Child).OneOrMore ();
+ }
+
+ internal override void CheckConstraints (bool attribute, bool oneOrMore, bool oneOrMoreGroup, bool oneOrMoreInterleave, bool list, bool dataExcept)
+ {
+ if (dataExcept)
+ throw new RelaxngException ("oneOrMore is not allowed under except of a data.");
+ this.Child.CheckConstraints (attribute, true, oneOrMoreGroup, oneOrMoreInterleave, list, dataExcept);
+ }
+ }
+
+ // List
+ public class RdpList : RdpAbstractSingleContent
+ {
+ public RdpList (RdpPattern p) : base (p)
+ {
+ }
+
+ internal override RdpPattern ReduceEmptyAndNotAllowed (ref bool result, Hashtable visited)
+ {
+ if (visited.Contains (this))
+ return this;
+ visited.Add (this, this);
+
+ if (Child.PatternType == RelaxngPatternType.NotAllowed) {
+ result = true;
+ return RdpNotAllowed.Instance;
+ } else {
+ Child = Child.ReduceEmptyAndNotAllowed (ref result, visited);
+ return this;
+ }
+ }
+
+ public override bool Nullable {
+ get { return false; }
+ }
+
+ internal override bool IsTextValueDependent {
+ get { return true; }
+ }
+
+ internal override bool IsContextDependent {
+ get { return Child.IsContextDependent; }
+ }
+
+ public override RelaxngPatternType PatternType {
+ get { return RelaxngPatternType.List; }
+ }
+
+ public override RdpContentType ContentType {
+ get { return RdpContentType.Simple; }
+ }
+
+ public override void GetLabels (LabelList elements, LabelList attributes, bool collectNameClass)
+ {
+ Child.GetLabels (elements, attributes, collectNameClass);
+ }
+
+ public override RdpPattern TextDeriv (string s, XmlReader reader)
+ {
+ s = Util.NormalizeWhitespace (s);
+
+ RdpPattern p = Child.ListDeriv (s.Split (RdpUtil.WhitespaceChars), 0, reader);
+ if (p.Nullable)
+ return RdpEmpty.Instance;
+ else
+ return RdpNotAllowed.Instance;
+ }
+
+ internal override void CheckConstraints (bool attribute, bool oneOrMore, bool oneOrMoreGroup, bool oneOrMoreInterleave, bool list, bool dataExcept)
+ {
+ if (list)
+ throw new RelaxngException ("list is not allowed uner another list.");
+ if (dataExcept)
+ throw new RelaxngException ("list is not allowed under except of a data.");
+ this.Child.CheckConstraints (attribute, oneOrMore, oneOrMoreGroup, oneOrMoreInterleave, true, dataExcept);
+ }
+ }
+
+ // Data
+ public class RdpData : RdpPattern
+ {
+ public RdpData (RdpDatatype dt)
+ {
+ this.dt = dt;
+ }
+
+ RdpDatatype dt;
+ public RdpDatatype Datatype {
+ get { return dt; }
+ }
+
+ public override bool Nullable {
+ get { return false; }
+ }
+
+ internal override bool IsTextValueDependent {
+ get { return true; }
+ }
+
+ internal override bool IsContextDependent {
+ get { return dt.IsContextDependent; }
+ }
+
+ public override RelaxngPatternType PatternType {
+ get { return RelaxngPatternType.Data; }
+ }
+
+ public override RdpContentType ContentType {
+ get { return RdpContentType.Simple; }
+ }
+
+ public override void GetLabels (LabelList elements, LabelList attributes, bool collectNameClass)
+ {
+ // do nothing.
+ }
+
+ public override RdpPattern TextDeriv (string s, XmlReader reader)
+ {
+ if (dt.IsAllowed (s, reader))
+ return RdpEmpty.Instance;
+ else
+ return RdpNotAllowed.Instance;
+ }
+
+ internal override void MarkReachableDefs ()
+ {
+ // do nothing
+ }
+
+ internal override void CheckConstraints (bool attribute, bool oneOrMore, bool oneOrMoreGroup, bool oneOrMoreInterleave, bool list, bool dataExcept)
+ {
+ // do nothing
+ }
+
+ internal override bool ContainsText()
+ {
+ return false;
+ }
+ }
+
+ // DataExcept
+ public class RdpDataExcept : RdpData
+ {
+ public RdpDataExcept (RdpDatatype dt, RdpPattern except)
+ : base (dt)
+ {
+ this.except = except;
+ }
+
+ RdpPattern except;
+ public RdpPattern Except {
+ get { return except; }
+ set { except = value; }
+ }
+
+ public override RelaxngPatternType PatternType {
+ get { return RelaxngPatternType.DataExcept; }
+ }
+
+ public override RdpContentType ContentType {
+ get {
+ RdpContentType c = except.ContentType; // conformance required for except pattern.
+ return RdpContentType.Simple;
+ }
+ }
+
+ internal override RdpPattern ReduceEmptyAndNotAllowed (ref bool result, Hashtable visited)
+ {
+ if (visited.Contains (this))
+ return this;
+ visited.Add (this, this);
+
+ if (except.PatternType == RelaxngPatternType.NotAllowed) {
+ result = true;
+ return new RdpData (this.Datatype);
+ } else {
+ except = except.ReduceEmptyAndNotAllowed (ref result, visited);
+ return this;
+ }
+ }
+
+ public override RdpPattern TextDeriv (string s, XmlReader reader)
+ {
+ if (Datatype.IsAllowed (s, reader) && !except.TextDeriv (s, reader).Nullable)
+ return RdpEmpty.Instance;
+ else
+ return RdpNotAllowed.Instance;
+ }
+
+ internal override void CheckConstraints (bool attribute, bool oneOrMore, bool oneOrMoreGroup, bool oneOrMoreInterleave, bool list, bool dataExcept)
+ {
+ this.except.CheckConstraints (attribute, oneOrMore, oneOrMoreGroup, oneOrMoreInterleave, list, true);
+ }
+
+ internal override bool ContainsText()
+ {
+ return except.ContainsText ();
+ }
+ }
+
+ // Value
+ public class RdpValue : RdpPattern
+ {
+ public RdpValue (RdpDatatype dt, string value)
+ {
+ this.dt = dt;
+ this.value = value;
+ }
+
+ RdpDatatype dt;
+ public RdpDatatype Datatype {
+ get { return dt; }
+ }
+
+ string value;
+ public string Value {
+ get { return value; }
+ }
+
+ public override bool Nullable {
+ get { return false; }
+ }
+
+ internal override bool IsTextValueDependent {
+ get { return true; }
+ }
+
+ internal override bool IsContextDependent {
+ get { return dt.IsContextDependent; }
+ }
+
+ public override RelaxngPatternType PatternType {
+ get { return RelaxngPatternType.Value; }
+ }
+
+ public override RdpContentType ContentType {
+ get { return RdpContentType.Simple; }
+ }
+
+ public override void GetLabels (LabelList elements, LabelList attributes, bool collectNameClass)
+ {
+ // 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;
+ else
+ return RdpNotAllowed.Instance;
+ }
+
+ internal override void MarkReachableDefs ()
+ {
+ // do nothing
+ }
+
+ internal override void CheckConstraints (bool attribute, bool oneOrMore, bool oneOrMoreGroup, bool oneOrMoreInterleave, bool list, bool dataExcept)
+ {
+ // nothing to be checked
+ }
+
+ internal override bool ContainsText()
+ {
+ return false;
+ }
+ }
+
+ // Attribute
+ public class RdpAttribute : RdpPattern
+ {
+ public RdpAttribute (RdpNameClass nameClass, RdpPattern p)
+ {
+ this.nameClass = nameClass;
+ this.children = p;
+ }
+
+ RdpNameClass nameClass;
+ public RdpNameClass NameClass {
+ get { return nameClass; }
+ }
+
+ RdpPattern children;
+ public RdpPattern Children {
+ get { return children; }
+ set { children = value; }
+ }
+
+ public override bool Nullable {
+ get { return false; }
+ }
+
+ internal override bool IsTextValueDependent {
+ get { return false; }
+ }
+
+ internal override bool IsContextDependent {
+ get { return false; }
+ }
+
+ public override RelaxngPatternType PatternType {
+ get { return RelaxngPatternType.Attribute; }
+ }
+
+ public override RdpContentType ContentType {
+ get { return RdpContentType.Empty; }
+ }
+
+ public override void GetLabels (LabelList elements, LabelList attributes, bool collectNameClass)
+ {
+ if (attributes != null) {
+ if (collectNameClass)
+ attributes [NameClass] = NameClass;
+ else
+ AddNameLabel (attributes, NameClass);
+ }
+ }
+
+ bool isExpanded;
+ internal override RdpPattern ExpandRef (Hashtable defs)
+ {
+ if (!isExpanded) {
+ isExpanded = true;
+ children = children.ExpandRef (defs);
+ }
+ return this;
+ }
+
+ internal override RdpPattern ReduceEmptyAndNotAllowed (ref bool result, Hashtable visited)
+ {
+ if (visited.Contains (this))
+ return this;
+ visited.Add (this, this);
+
+ if (children.PatternType == RelaxngPatternType.NotAllowed) {
+ result = true;
+ return RdpNotAllowed.Instance;
+ } else {
+ children = children.ReduceEmptyAndNotAllowed (ref result, visited);
+ return this;
+ }
+ }
+
+ // attDeriv cx (Attribute nc p) (AttributeNode qn s) =
+ // if contains nc qn && valueMatch cx p s then Empty else NotAllowed
+ public override RdpPattern AttDeriv (string name, string ns, string value, XmlReader reader)
+ {
+ // If value is null, then does not check ValueMatch.
+#if UseStatic
+ if (RdpUtil.Contains (this.nameClass, att.QName)
+ && (value == null || RdpUtil.ValueMatch (ctx, this.children, att.Value)))
+ return RdpEmpty.Instance;
+ else
+ return RdpNotAllowed.Instance;
+#else
+ if (nameClass.Contains (name, ns) &&
+ (value == null || children.ValueMatch (value, reader)))
+ return RdpEmpty.Instance;
+ else
+ return RdpNotAllowed.Instance;
+#endif
+ }
+
+ public override RdpPattern StartAttDeriv (string name, string ns)
+ {
+ return nameClass.Contains (name, ns) ?
+ children.After (RdpEmpty.Instance) : RdpNotAllowed.Instance;
+ }
+
+ internal override RdpPattern StartAttDeriv (string name, string ns, MemoizationStore memo)
+ {
+ return nameClass.Contains (name, ns) ?
+ children.After (RdpEmpty.Instance) : RdpNotAllowed.Instance;
+ }
+
+ // startTagCloseDeriv (Attribute _ _) = NotAllowed
+ public override RdpPattern StartTagCloseDeriv ()
+ {
+ return RdpNotAllowed.Instance;
+ }
+
+ internal override RdpPattern StartTagCloseDeriv (MemoizationStore memo)
+ {
+ return RdpNotAllowed.Instance;
+ }
+
+ internal override void MarkReachableDefs ()
+ {
+ children.MarkReachableDefs ();
+ }
+
+ internal override void CheckConstraints (bool attribute, bool oneOrMore, bool oneOrMoreGroup, bool oneOrMoreInterleave, bool list, bool dataExcept)
+ {
+ // 7.1.1 and 7.1.2
+ if (attribute || oneOrMoreGroup || oneOrMoreInterleave || list || dataExcept)
+ throw new RelaxngException ("Not allowed attribute occurence was specified in the pattern.");
+
+ // latter part of 7.3
+ if (!oneOrMore && NameClass.HasInfiniteName)
+ throw new RelaxngException ("Attributes that has an infinite name class must be repeatable.");
+
+ this.Children.CheckConstraints (true, oneOrMore, false, false, false, false);
+ }
+
+ internal override bool ContainsText()
+ {
+ // This method is to detect text pattern inside interleave child.
+ // return children.ContainsText ();
+ return false;
+ }
+ }
+
+ // Element
+ public class RdpElement : RdpPattern
+ {
+ public RdpElement (RdpNameClass nameClass, RdpPattern p)
+ {
+ this.nameClass = nameClass;
+ this.children = p;
+ }
+
+ RdpNameClass nameClass;
+ public RdpNameClass NameClass {
+ get { return nameClass; }
+ }
+
+ RdpPattern children;
+ public RdpPattern Children {
+ get { return children; }
+ set { children = value; }
+ }
+
+ public override bool Nullable {
+ get { return false; }
+ }
+
+ internal override bool IsTextValueDependent {
+ get { return false; }
+ }
+
+ internal override bool IsContextDependent {
+ get { return false; }
+ }
+
+ public override RelaxngPatternType PatternType {
+ get { return RelaxngPatternType.Element; }
+ }
+
+ bool contentTypeCheckDone;
+ public override RdpContentType ContentType {
+ get {
+ if (!contentTypeCheckDone) {
+ contentTypeCheckDone = true;
+ RdpContentType ct = children.ContentType; // conformance required.
+ }
+ return RdpContentType.Complex;
+ }
+ }
+
+ public override void GetLabels (LabelList elements, LabelList attributes, bool collectNameClass)
+ {
+ if (elements != null) {
+ if (collectNameClass)
+ elements [NameClass] = NameClass;
+ else
+ AddNameLabel (elements, NameClass);
+ }
+ }
+
+
+ bool isExpanded;
+ short expanding; // FIXME: It is totally not required, but there is
+ // some bugs in simplification and without it it causes infinite loop.
+ internal override RdpPattern ExpandRef (Hashtable defs)
+ {
+ if (!isExpanded) {
+ isExpanded = true;
+ if (expanding == 100)
+ throw new RelaxngException (String.Format ("Invalid recursion was found. Name is {0}", nameClass));
+ expanding++;
+ children = children.ExpandRef (defs);
+ expanding--;
+ }
+ return this;
+ }
+
+ internal override RdpPattern ReduceEmptyAndNotAllowed (ref bool result, Hashtable visited)
+ {
+ if (visited.Contains (this))
+ return this;
+ visited.Add (this, this);
+
+ children = children.ReduceEmptyAndNotAllowed (ref result, visited);
+ return this;
+ }
+
+ internal override RdpPattern TextOnlyDeriv ()
+ {
+ return RdpNotAllowed.Instance;
+ }
+
+ internal override RdpPattern TextOnlyDeriv (MemoizationStore memo)
+ {
+ return RdpNotAllowed.Instance;
+ }
+
+ public override RdpPattern StartTagOpenDeriv (string name, string ns)
+ {
+#if UseStatic
+ if (RdpUtil.Contains (this.nameClass, qname))
+ return RdpUtil.After (this.Children, RdpEmpty.Instance);
+ else
+ return RdpNotAllowed.Instance;
+#else
+ return nameClass.Contains (name, ns) ?
+ children.After (RdpEmpty.Instance) :
+ RdpNotAllowed.Instance;
+#endif
+ }
+
+ internal override RdpPattern StartTagOpenDeriv (string name, string ns, MemoizationStore memo)
+ {
+ return nameClass.Contains (name, ns) ?
+ children.After (RdpEmpty.Instance) :
+ RdpNotAllowed.Instance;
+ }
+
+ internal override void MarkReachableDefs ()
+ {
+ children.MarkReachableDefs ();
+ }
+
+ bool constraintsChecked;
+ internal override void CheckConstraints (bool attribute, bool oneOrMore, bool oneOrMoreGroup, bool oneOrMoreInterleave, bool list, bool dataExcept)
+ {
+ if (constraintsChecked)
+ return;
+ constraintsChecked = true;
+ if (attribute || list || dataExcept)
+ throw new RelaxngException ("Not allowed element occurence was specified in the pattern.");
+ this.Children.CheckConstraints (false, oneOrMore, oneOrMoreGroup, oneOrMoreInterleave, false, false);
+ }
+
+ internal override bool ContainsText()
+ {
+ return children.ContainsText ();
+ }
+ }
+
+ // After
+ public class RdpAfter : RdpAbstractBinary
+ {
+ public RdpAfter (RdpPattern l, RdpPattern r) : base (l, r)
+ {
+ }
+
+ public override bool Nullable {
+ get { return false; }
+ }
+
+ internal override bool IsTextValueDependent {
+ 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);
+ }
+
+ public override RdpPattern TextDeriv (string s, XmlReader reader)
+ {
+ 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);
+ }
+
+ internal override RdpPattern TextOnlyDeriv (MemoizationStore memo)
+ {
+ return memo.TextOnlyDeriv (LValue).After (RValue);
+ }
+
+ internal override RdpPattern MixedTextDeriv ()
+ {
+ return LValue.MixedTextDeriv ().After (RValue);
+ }
+
+ internal override RdpPattern MixedTextDeriv (MemoizationStore memo)
+ {
+ return memo.MixedTextDeriv (LValue).After (RValue);
+ }
+
+ // startTagOpenDeriv (After p1 p2) qn =
+ // applyAfter (flip after p2) (startTagOpenDeriv p1 qn)
+ public override RdpPattern StartTagOpenDeriv (string name, string ns)
+ {
+ RdpPattern handled = LValue.StartTagOpenDeriv (name, ns);
+ RdpFlip f = MakeFlip (RdpUtil.AfterFunction, RValue);
+ return handled.ApplyAfter (new RdpApplyAfterHandler (
+ f.Apply));
+ }
+
+ internal override RdpPattern StartTagOpenDeriv (string name, string ns, MemoizationStore memo)
+ {
+ RdpPattern handled = memo.StartTagOpenDeriv (LValue, name, ns);
+ RdpFlip f = MakeFlip (RdpUtil.AfterFunction, RValue);
+ return handled.ApplyAfter (new RdpApplyAfterHandler (
+ f.Apply));
+ }
+
+ public override RdpPattern ApplyAfter (RdpApplyAfterHandler handler)
+ {
+ return LValue.After (handler (RValue));
+ }
+
+ // attDeriv cx (After p1 p2) att =
+ // after (attDeriv cx p1 att) p2
+ public override RdpPattern AttDeriv (string name, string ns, string value, XmlReader reader)
+ {
+ return LValue.AttDeriv (name, ns, value, reader).After (RValue);
+ }
+
+ public override RdpPattern StartAttDeriv (string name, string ns)
+ {
+ RdpPattern handled = LValue.StartAttDeriv (name, ns);
+ RdpFlip f = MakeFlip (RdpUtil.AfterFunction, RValue);
+ return handled.ApplyAfter (new RdpApplyAfterHandler (
+ f.Apply));
+ }
+
+ internal override RdpPattern StartAttDeriv (string name, string ns, MemoizationStore memo)
+ {
+ RdpPattern handled = memo.StartAttDeriv (LValue, name, ns);
+ RdpFlip f = MakeFlip (RdpUtil.AfterFunction, RValue);
+ return handled.ApplyAfter (new RdpApplyAfterHandler (
+ f.Apply));
+ }
+
+ public override RdpPattern EndAttDeriv ()
+ {
+ return LValue.Nullable ? RValue : RdpNotAllowed.Instance;
+ }
+
+ public override RdpPattern StartTagCloseDeriv ()
+ {
+ return LValue.StartTagCloseDeriv ().After (RValue);
+ }
+
+ internal override RdpPattern StartTagCloseDeriv (MemoizationStore memo)
+ {
+ return memo.StartTagCloseDeriv (LValue).After (RValue);
+ }
+
+ public override RdpPattern EndTagDeriv ()
+ {
+ return LValue.Nullable ? RValue : RdpNotAllowed.Instance;
+ }
+
+ public override RelaxngPatternType PatternType {
+ get { return RelaxngPatternType.After; }
+ }
+
+ internal override void MarkReachableDefs ()
+ {
+ throw new InvalidOperationException ();
+ }
+
+ internal override void CheckConstraints (bool attribute, bool oneOrMore, bool oneOrMoreGroup, bool oneOrMoreInterleave, bool list, bool dataExcept)
+ {
+ throw new InvalidOperationException ();
+ }
+
+ internal override bool ContainsText ()
+ {
+ throw new InvalidOperationException ();
+ }
+ }
+}
+