internal override void CalcFollowpos(BitSet[] followpos) { int i, l; BitSet lp, fp; switch (contentType) { case Type.Sequence: left.CalcFollowpos(followpos); right.CalcFollowpos(followpos); l = followpos.Length; lp = left.Lastpos(l); fp = right.Firstpos(l); for (i = followpos.Length - 1; i >= 0; i--) { if (lp.Get(i)) { followpos[i].Or(fp); } } break; case Type.Choice: left.CalcFollowpos(followpos); right.CalcFollowpos(followpos); break; case Type.Qmark: left.CalcFollowpos(followpos); break; case Type.Star: case Type.Plus: left.CalcFollowpos(followpos); l = followpos.Length; Lastpos(l); Firstpos(l); for (i = followpos.Length - 1; i >= 0; i--) { if (last.Get(i)) { followpos[i].Or(first); } } break; default: throw new XmlException(Res.Xml_InternalError); } }
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; }