protected ContentNode right; // right node // if node type is QMark, Closure, or Type.Plus, right node is NULL internal InternalNode(ContentNode l, ContentNode r, ContentNode.Type t) { left = l; right = r; contentType = t; }
internal void Finish(ValidationEventHandler eventHandler, bool compile) { stack = null; IsCompiled = !abnormalContent && compile; if (contentNode == null) { return; } #if DEBUG StringBuilder bb = new StringBuilder(); contentNode.Dump(bb); Debug.WriteLineIf(CompModSwitches.XmlSchema.TraceVerbose, "\t\t\tContent: (" + bb.ToString() + ")"); #endif // add end node endNode = NewTerminalNode(XmlQualifiedName.Empty); contentNode = new InternalNode(contentNode, endNode, ContentNode.Type.Sequence); ((InternalNode)contentNode).LeftNode.ParentNode = contentNode; endNode.ParentNode = contentNode; if (!IsCompiled) { CheckXsdDeterministic(eventHandler); return; } if (nodeTable == null) { nodeTable = new Hashtable(); } // calculate followpos int terminals = terminalNodes.Count; BitSet[] followpos = new BitSet[terminals]; for (int i = 0; i < terminals; i++) { followpos[i] = new BitSet(terminals); } contentNode.CalcFollowpos(followpos); // state table ArrayList Dstates = new ArrayList(16); // transition table dtrans = new ArrayList(16); // lists unmarked states ArrayList unmarked = new ArrayList(16); // state lookup table Hashtable statetable = new Hashtable(); BitSet empty = new BitSet(terminals); statetable.Add(empty, -1); // start with firstpos at the root BitSet set = contentNode.Firstpos(terminals); statetable.Add(set, Dstates.Count); unmarked.Add(set); Dstates.Add(set); int[] a = new int[symbols.Count + 1]; dtrans.Add(a); if (set.Get(endNode.Pos)) { a[symbols.Count] = 1; // accepting } // current state processed int state = 0; // check all unmarked states while (unmarked.Count > 0) { int[] t = (int[])dtrans[state]; set = (BitSet)unmarked[0]; CheckDeterministic(set, terminals, eventHandler); unmarked.RemoveAt(0); // check all input symbols for (int sym = 0; sym < symbols.Count; sym++) { XmlQualifiedName n = (XmlQualifiedName)symbols[sym]; BitSet newset = new BitSet(terminals); // if symbol is in the set add followpos to new set for (int i = 0; i < terminals; i++) { if (set.Get(i) && n.Equals(((TerminalNode)terminalNodes[i]).Name)) { 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 = Dstates.Count; statetable.Add(newset, transitionTo); unmarked.Add(newset); Dstates.Add(newset); a = new int[symbols.Count + 1]; dtrans.Add(a); if (newset.Get(endNode.Pos)) { a[symbols.Count] = 1; // accepting } } else { transitionTo = (int)lookup; } // set the transition for the symbol t[sym] = transitionTo; } state++; } nodeTable = null; }
private void CheckXsdContent(ValidationState context, XmlQualifiedName qname, ref XmlSchemaContentProcessing processContents) { ContentNode cnode = context.CurrentNode; Object lookup = symbolTable[qname]; int terminals = symbols.Count; MinMaxNode ln; InternalNode inNode; MinMaxValues mm; int NodeMatched = context.HasNodeMatched; while (true) { switch (cnode.NodeType) { case ContentNode.Type.Any: case ContentNode.Type.Terminal: context.HasNodeMatched = (((InternalNode)cnode.ParentNode).LeftNode == cnode) ? 1 : 2; context.CurrentNode = cnode.ParentNode; context.HasMatched = (cnode.ParentNode == endNode); if (cnode.NodeType == ContentNode.Type.Any) { processContents = ((AnyNode)cnode).ProcessContents; } return; case ContentNode.Type.Sequence: inNode = (InternalNode)cnode; if (NodeMatched == 0) { if (Accepts(inNode.LeftNode, qname, terminals, lookup)) { cnode = inNode.LeftNode; break; } else if (inNode.LeftNode.Nullable()) { NodeMatched = 1; } else { goto error; } } if (NodeMatched == 1) { if (Accepts(inNode.RightNode, qname, terminals, lookup)) { NodeMatched = 0; cnode = inNode.RightNode; break; } else if (inNode.RightNode.Nullable()) { NodeMatched = 2; } else { goto error; } } if (NodeMatched == 2) { if (cnode.ParentNode != null) { if (((InternalNode)cnode.ParentNode).LeftNode == cnode) { NodeMatched = 1; } cnode = cnode.ParentNode; break; } else { goto error; } } break; case ContentNode.Type.Choice: inNode = (InternalNode)cnode; if (NodeMatched != 0) { NodeMatched = (((InternalNode)cnode.ParentNode).LeftNode == cnode) ? 1 : 2; cnode = cnode.ParentNode; } else if (Accepts(inNode.LeftNode, qname, terminals, lookup)) { NodeMatched = 0; cnode = inNode.LeftNode; } else if (Accepts(inNode.RightNode, qname, terminals, lookup)) { NodeMatched = 0; cnode = inNode.RightNode; } else { goto error; } break; case ContentNode.Type.Qmark: inNode = (InternalNode)cnode; if (NodeMatched != 0) { NodeMatched = (((InternalNode)cnode.ParentNode).LeftNode == cnode) ? 1 : 2; cnode = cnode.ParentNode; } else if (Accepts(inNode.LeftNode, qname, terminals, lookup)) { cnode = inNode.LeftNode; } else { goto error; } break; case ContentNode.Type.Star: case ContentNode.Type.Plus: inNode = (InternalNode)cnode; if (Accepts(inNode.LeftNode, qname, terminals, lookup)) { NodeMatched = 0; cnode = inNode.LeftNode; } else { NodeMatched = (((InternalNode)cnode.ParentNode).LeftNode == cnode) ? 1 : 2; cnode = cnode.ParentNode; } break; case ContentNode.Type.MinMax: inNode = (InternalNode)cnode; ln = (MinMaxNode)cnode; mm = null; if (context.MinMaxValues != null) { mm = (MinMaxValues)context.MinMaxValues[ln]; } else { context.MinMaxValues = new Hashtable(); } if (mm == null) { // new minmaxnode and add it to minmaxnodes hashtable mm = new MinMaxValues(ln.Min, ln.Max); context.MinMaxValues.Add(ln, mm); } if (mm.Max == 0) { NodeMatched = (((InternalNode)cnode.ParentNode).LeftNode == cnode) ? 1 : 2; cnode = cnode.ParentNode; mm.Max = ln.Max; mm.Min = ln.Min; } else if (Accepts(inNode.LeftNode, qname, terminals, lookup)) { mm.Max -= 1; mm.Min -= 1; NodeMatched = 0; cnode = inNode.LeftNode; } else { if (mm.Min > 0) { goto error; } NodeMatched = (((InternalNode)cnode.ParentNode).LeftNode == cnode) ? 1 : 2; cnode = cnode.ParentNode; mm.Max = ln.Max; mm.Min = ln.Min; } break; } // switch } // while (true) error: context.NeedValidateChildren = false; ArrayList v = ExpectedXsdElements(context.CurrentNode, NodeMatched); if (v == null) { throw new XmlSchemaException(Res.Sch_InvalidContent, context.Name.ToString()); } else { throw new XmlSchemaException(Res.Sch_InvalidContentExpecting, new string[] { context.Name.ToString(), v.ToString() }); } }
// returns names of all legal elements following the specified state private ArrayList ExpectedXsdElements(ContentNode cnode, int NodeMatched) { return(null); }