internal CompiledParticleContentValidator(ValidationState context, InternalNode contentRoot, NamedNode[] namedTerminals, Hashtable symbols, int symCount, bool isOpen, XmlSchemaContentType contentType, Member mixed, NamedNode endMarker) : base(contentType, namedTerminals, symbols, contentRoot, endMarker, symCount, mixed) { // keep these this.isOpen = isOpen; this.isEmptiable = contentRoot.LeftChild.IsNullable; int terminalsCount = namedTerminals.Length; int endMarkerPos = terminalsCount - 1; // calculate followpos BitSet[] followpos = new BitSet[terminalsCount]; for (int i = 0; i < terminalsCount; i++) { followpos[i] = new BitSet(terminalsCount); } contentRoot.CalcFollowpos(followpos); // transition table ArrayList transitionTable = new ArrayList(); // state lookup table Hashtable stateTable = new Hashtable(); // lists unmarked states ArrayList unmarked = new ArrayList(); stateTable.Add(new BitSet(terminalsCount), -1); // add empty // start with firstpos at the root BitSet firstpos = contentRoot.Firstpos; stateTable.Add(firstpos, 0); unmarked.Add(firstpos); int[] a = new int[symbolCount + 1]; transitionTable.Add(a); if (firstpos[endMarkerPos]) { a[symbolCount] = 1; // accepting } // current state processed int state = 0; // check all unmarked states while (unmarked.Count > 0) { int[] t = (int[])transitionTable[state]; firstpos = (BitSet)unmarked[0]; if (!isNonDeterministic && !CheckDeterministic(firstpos, namedTerminals, context)) { isNonDeterministic = true; } unmarked.RemoveAt(0); // check all input symbols foreach (NamedNodeList list in symbols.Values){ foreach (NamedNode node in list) { BitSet newset = new BitSet(terminalsCount); // if symbol is in the set add followpos to new set for (int i = 0; i < terminalsCount; i++) { if (firstpos[i] && node == namedTerminals[i]) { newset.Or(followpos[i]); } } object lookup = stateTable[newset]; // this state will transition to int transitionTo; // if new set is not in states add it if (lookup == null) { transitionTo = stateTable.Count - 1; stateTable.Add(newset, transitionTo); unmarked.Add(newset); a = new int[symbolCount + 1]; transitionTable.Add(a); if (newset[endMarkerPos]) { a[symbolCount] = 1; // accepting } } else { transitionTo = (int)lookup; } // set the transition for the symbol t[node.Symbol] = transitionTo; } } state++; } // now convert transition table to array this.transitionTable = (int[][])transitionTable.ToArray(typeof(int[])); }
private void Closure(InternalNode node) { if (stack.Count > 0) { ContentNode topNode = (ContentNode)stack.Pop(); if (isPartial && !topNode.IsTerminal) { // need to reach in and wrap _pRight hand side of element. // and n remains the same. InternalNode inNode = (InternalNode)topNode; node.LeftChild = inNode.RightChild; node.Parent = inNode; if (inNode.RightChild != null) { inNode.RightChild.Parent = node; } inNode.RightChild = node; } else { // wrap terminal or any node if (topNode != null) topNode.Parent = node; node.LeftChild = topNode; topNode = node; } stack.Push(topNode); } else { // wrap whole content node.LeftChild = contentNode; contentNode.Parent = node; contentNode = node; } }
public ParticleContentValidator(XmlSchemaContentType contentType, NamedNode[] namedTerminals, Hashtable symbols, InternalNode contentRoot, NamedNode endMarker, int symbolCount, Member mixed) : base(contentType, mixed) { this.namedTerminals = namedTerminals; this.symbols = symbols; this.contentRoot = contentRoot; this.endMarker = endMarker; this.symbolCount = symbolCount; }
public ContentValidator Finish(ValidationState context, bool compile) { Debug.Assert(contentType == XmlSchemaContentType.ElementOnly || contentType == XmlSchemaContentType.Mixed); if (contentNode == null) { if (contentType == XmlSchemaContentType.Mixed) { string ctype = IsOpen ? "Any" : "TextOnly"; return IsOpen ? ContentValidator.Any : new ContentValidator(XmlSchemaContentType.TextOnly, this.MixedMember); } else { Debug.Assert(!IsOpen); return ContentValidator.Empty; } } // add end node contentRoot = new SequenceNode(null,null); contentNode.Parent = contentRoot; contentRoot.LeftChild = contentNode; endMarker = NewNamedTerminal(Identifier.Empty, null, null); endMarker.Parent = contentRoot; contentRoot.RightChild = endMarker; namedTerminals = (NamedNode[])namedTerminalsArray.ToArray(typeof(NamedNode)); namedTerminalsArray = null; contentRoot.ConstructPos(namedTerminals.Length); // bugbug: I need to figure out how to get the real terminals // back out of the state machine. Currently the state machine treats all terminals // with the same name as the same terminal, which is not what I want. I need // the NamedNode with the right member bindings. if (canCompile && compile) { return new CompiledParticleContentValidator(context, this.contentRoot, this.namedTerminals, this.symbols, this.symbolCount, this.IsOpen, this.contentType, this.MixedMember, endMarker); } else { Debug.Assert(!IsOpen); // only deal with compiled XDR open content model return new ParticleContentValidator(this.contentType, this.namedTerminals, this.symbols, this.contentRoot, this.endMarker, this.symbolCount, this.MixedMember); } }