示例#1
0
        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;
        }