ANTLR_BEGIN_NAMESPACE()

template< class ImplTraits, class DataType >
ANTLR_INLINE TrieEntry<ImplTraits, DataType>::TrieEntry(const DataType& data, TrieEntry* next)
	:m_data(data)
{
	m_next = next;
}
template< class ImplTraits, class DataType >
ANTLR_INLINE DataType& TrieEntry<ImplTraits, DataType>::get_data()
{
	return m_data;
}
template< class ImplTraits, class DataType >
ANTLR_INLINE const DataType& TrieEntry<ImplTraits, DataType>::get_data() const
{
	return m_data;
}
template< class ImplTraits, class DataType >
ANTLR_INLINE TrieEntry<ImplTraits, DataType>* TrieEntry<ImplTraits, DataType>::get_next() const
{
	return m_next;
}

template< class ImplTraits, class DataType >
ANTLR_INLINE void TrieEntry<ImplTraits, DataType>::set_next( TrieEntry* next )
{
	m_next = next;
}

template< class ImplTraits, class DataType >
ANTLR_INLINE ANTLR_UINT32 IntTrieNode<ImplTraits, DataType>::get_bitNum() const
{
	return m_bitNum;
}
template< class ImplTraits, class DataType >
ANTLR_INLINE ANTLR_INTKEY IntTrieNode<ImplTraits, DataType>::get_key() const
{
	return m_key;
}
template< class ImplTraits, class DataType >
ANTLR_INLINE typename IntTrieNode<ImplTraits, DataType>::BucketsType* IntTrieNode<ImplTraits, DataType>::get_buckets() const
{
	return m_buckets;
}
template< class ImplTraits, class DataType >
ANTLR_INLINE IntTrieNode<ImplTraits, DataType>* IntTrieNode<ImplTraits, DataType>::get_leftN() const
{
	return m_leftN;
}
template< class ImplTraits, class DataType >
ANTLR_INLINE IntTrieNode<ImplTraits, DataType>* IntTrieNode<ImplTraits, DataType>::get_rightN() const
{
	return m_rightN;
}
template< class ImplTraits, class DataType >
ANTLR_INLINE void IntTrieNode<ImplTraits, DataType>::set_bitNum( ANTLR_UINT32 bitNum )
{
	m_bitNum = bitNum;
}
template< class ImplTraits, class DataType >
ANTLR_INLINE void IntTrieNode<ImplTraits, DataType>::set_key( ANTLR_INTKEY key )
{
	m_key = key;
}
template< class ImplTraits, class DataType >
ANTLR_INLINE void IntTrieNode<ImplTraits, DataType>::set_buckets( BucketsType* buckets )
{
	m_buckets = buckets;
}
template< class ImplTraits, class DataType >
ANTLR_INLINE void IntTrieNode<ImplTraits, DataType>::set_leftN( IntTrieNode* leftN )
{
	m_leftN = leftN;
}
template< class ImplTraits, class DataType >
ANTLR_INLINE void IntTrieNode<ImplTraits, DataType>::set_rightN( IntTrieNode* rightN )
{
	m_rightN = rightN;
}

ANTLR_INLINE const ANTLR_UINT8* IntTrieBase::get_bitIndex()
{
	static ANTLR_UINT8 bitIndex[256] = 
	{ 
		0,													// 0 - Just for padding
		0,													// 1
		1, 1,												// 2..3
		2, 2, 2, 2,											// 4..7
		3, 3, 3, 3, 3, 3, 3, 3,								// 8+
		4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,	    // 16+
		5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,	    // 32+
		5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,	    
		6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,	    // 64+
		6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
		6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
		6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 
		7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,	    // 128+
		7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
		7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
		7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
		7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
		7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 
		7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
		7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
	};
	return bitIndex;
}

ANTLR_INLINE const ANTLR_UINT64* IntTrieBase::get_bitMask()
{
	static ANTLR_UINT64 bitMask[64] = 
	{
		0x0000000000000001ULL, 0x0000000000000002ULL, 0x0000000000000004ULL, 0x0000000000000008ULL,
		0x0000000000000010ULL, 0x0000000000000020ULL, 0x0000000000000040ULL, 0x0000000000000080ULL,
		0x0000000000000100ULL, 0x0000000000000200ULL, 0x0000000000000400ULL, 0x0000000000000800ULL,
		0x0000000000001000ULL, 0x0000000000002000ULL, 0x0000000000004000ULL, 0x0000000000008000ULL,
		0x0000000000010000ULL, 0x0000000000020000ULL, 0x0000000000040000ULL, 0x0000000000080000ULL,
		0x0000000000100000ULL, 0x0000000000200000ULL, 0x0000000000400000ULL, 0x0000000000800000ULL,
		0x0000000001000000ULL, 0x0000000002000000ULL, 0x0000000004000000ULL, 0x0000000008000000ULL,
		0x0000000010000000ULL, 0x0000000020000000ULL, 0x0000000040000000ULL, 0x0000000080000000ULL,
		0x0000000100000000ULL, 0x0000000200000000ULL, 0x0000000400000000ULL, 0x0000000800000000ULL,
		0x0000001000000000ULL, 0x0000002000000000ULL, 0x0000004000000000ULL, 0x0000008000000000ULL,
		0x0000010000000000ULL, 0x0000020000000000ULL, 0x0000040000000000ULL, 0x0000080000000000ULL,
		0x0000100000000000ULL, 0x0000200000000000ULL, 0x0000400000000000ULL, 0x0000800000000000ULL,
		0x0001000000000000ULL, 0x0002000000000000ULL, 0x0004000000000000ULL, 0x0008000000000000ULL,
		0x0010000000000000ULL, 0x0020000000000000ULL, 0x0040000000000000ULL, 0x0080000000000000ULL,
		0x0100000000000000ULL, 0x0200000000000000ULL, 0x0400000000000000ULL, 0x0800000000000000ULL,
		0x1000000000000000ULL, 0x2000000000000000ULL, 0x4000000000000000ULL, 0x8000000000000000ULL
	};

	return bitMask;
}

template< class ImplTraits, class DataType >
IntTrie<ImplTraits, DataType>::IntTrie( ANTLR_UINT32 depth )
{
	/* Now we need to allocate the root node. This makes it easier
	 * to use the tree as we don't have to do anything special 
	 * for the root node.
	 */
	m_root	= new IntTrieNodeType;

	/* Now we seed the root node with the index being the
	 * highest left most bit we want to test, which limits the
	 * keys in the trie. This is the trie 'depth'. The limit for
	 * this implementation is 63 (bits 0..63).
	 */
	m_root->set_bitNum( depth );

	/* And as we have nothing in here yet, we set both child pointers
	 * of the root node to point back to itself.
	 */
	m_root->set_leftN( m_root );
	m_root->set_rightN( m_root );
	m_count			= 0;

	/* Finally, note that the key for this root node is 0 because
	 * we use calloc() to initialise it.
	 */
	m_allowDups = false;
	m_current   = NULL;
}

template< class ImplTraits, class DataType >
IntTrie<ImplTraits, DataType>::~IntTrie()
{
    /* Descend from the root and free all the nodes
     */
    delete m_root;

    /* the nodes are all gone now, so we need only free the memory
     * for the structure itself
     */
}

template< class ImplTraits, class DataType >
typename IntTrie<ImplTraits, DataType>::TrieEntryType*	IntTrie<ImplTraits, DataType>::get( ANTLR_INTKEY key)
{
	IntTrieNodeType*    thisNode; 
	IntTrieNodeType*    nextNode; 

	if (m_count == 0)
		return NULL;	    /* Nothing in this trie yet	*/

	/* Starting at the root node in the trie, compare the bit index
	 * of the current node with its next child node (starts left from root).
	 * When the bit index of the child node is greater than the bit index of the current node
	 * then by definition (as the bit index decreases as we descent the trie)
	 * we have reached a 'backward' pointer. A backward pointer means we
	 * have reached the only node that can be reached by the bits given us so far
	 * and it must either be the key we are looking for, or if not then it
	 * means the entry was not in the trie, and we return NULL. A backward pointer
	 * points back in to the tree structure rather than down (deeper) within the
	 * tree branches.
	 */
	thisNode	= m_root;		/* Start at the root node		*/
	nextNode	= thisNode->get_leftN();	/* Examine the left node from the root	*/

	/* While we are descending the tree nodes...
	 */
	const ANTLR_UINT64* bitMask = this->get_bitMask();
	while( thisNode->get_bitNum() > nextNode->get_bitNum() )
	{
		/* Next node now becomes the new 'current' node
		 */
		thisNode    = nextNode;

		/* We now test the bit indicated by the bitmap in the next node
		 * in the key we are searching for. The new next node is the
		 * right node if that bit is set and the left node it is not.
		 */
		if (key & bitMask[nextNode->get_bitNum()])
		{
			nextNode = nextNode->get_rightN();	/* 1 is right	*/
		}
		else
		{
			nextNode = nextNode->get_leftN();		/* 0 is left	*/
		}
	}

	/* Here we have reached a node where the bitMap index is lower than
	 * its parent. This means it is pointing backward in the tree and
	 * must therefore be a terminal node, being the only point than can
	 * be reached with the bits seen so far. It is either the actual key
	 * we wanted, or if that key is not in the trie it is another key
	 * that is currently the only one that can be reached by those bits.
	 * That situation would obviously change if the key was to be added
	 * to the trie.
	 *
	 * Hence it only remains to test whether this is actually the key or not.
	 */
	if (nextNode->get_key() == key)
	{
		/* This was the key, so return the entry pointer
		 */
		return	nextNode->get_buckets();
	}
	else
	{
		return	NULL;	/* That key is not in the trie (note that we set the pointer to -1 if no payload) */
	}
}

template< class ImplTraits, class DataType >
bool	IntTrie<ImplTraits, DataType>::del( ANTLR_INTKEY key)
{
    IntTrieNodeType*   p;

    p = m_root;
    
    return false;

}

template< class ImplTraits, class DataType >
bool	IntTrie<ImplTraits, DataType>::add( ANTLR_INTKEY key, const DataType& data  )
{
	IntTrieNodeType*   thisNode;
	IntTrieNodeType*   nextNode;
	IntTrieNodeType*   entNode;
	ANTLR_UINT32	depth;
	TrieEntryType*	    newEnt;
	TrieEntryType*	    nextEnt;
	ANTLR_INTKEY		    xorKey;

	/* Cache the bit depth of this trie, which is always the highest index, 
	 * which is in the root node
	 */
	depth   = m_root->get_bitNum();

	thisNode	= m_root;		/* Start with the root node	    */
	nextNode	= m_root->get_leftN();	/* And assume we start to the left  */

	/* Now find the only node that can be currently reached by the bits in the
	 * key we are being asked to insert.
	 */
	const ANTLR_UINT64* bitMask = this->get_bitMask();
	while (thisNode->get_bitNum()  > nextNode->get_bitNum() )
	{
		/* Still descending the structure, next node becomes current.
		 */
		thisNode = nextNode;

		if (key & bitMask[nextNode->get_bitNum()])
		{
			/* Bit at the required index was 1, so travers the right node from here
			 */
			nextNode = nextNode->get_rightN();
		}
		else
		{
			/* Bit at the required index was 0, so we traverse to the left
			 */
			nextNode = nextNode->get_leftN();
		}
	}
	/* Here we have located the only node that can be reached by the
	 * bits in the requested key. It could in fact be that key or the node
	 * we need to use to insert the new key.
	 */
	if (nextNode->get_key() == key)
	{
		/* We have located an exact match, but we will only append to the bucket chain
		 * if this trie accepts duplicate keys.
		 */
		if (m_allowDups ==true)
		{
			/* Yes, we are accepting duplicates
			 */
			newEnt = new TrieEntryType(data, NULL);

			/* We want to be able to traverse the stored elements in the order that they were
			 * added as duplicate keys. We might need to revise this opinion if we end up having many duplicate keys
			 * as perhaps reverse order is just as good, so long as it is ordered.
			 */
			nextEnt = nextNode->get_buckets();
			while (nextEnt->get_next() != NULL)
			{
				nextEnt = nextEnt->get_next();    
			}
			nextEnt->set_next(newEnt);

			m_count++;
			return  true;
		}
		else
		{
			/* We found the key is already there and we are not allowed duplicates in this
			 * trie.
			 */
			return  false;
		}
	}

	/* Here we have discovered the only node that can be reached by the bits in the key
	 * but we have found that this node is not the key we need to insert. We must find the
	 * the leftmost bit by which the current key for that node and the new key we are going 
	 * to insert, differ. While this nested series of ifs may look a bit strange, experimentation
	 * showed that it allows a machine code path that works well with predicated execution
	 */
	xorKey = (key ^ nextNode->get_key() );   /* Gives 1 bits only where they differ then we find the left most 1 bit*/

	/* Most common case is a 32 bit key really
	 */
	const ANTLR_UINT8* bitIndex = this->get_bitIndex();
#ifdef	ANTLR_USE_64BIT
	if	(xorKey & 0xFFFFFFFF00000000)
	{
		if  (xorKey & 0xFFFF000000000000)
		{
			if	(xorKey & 0xFF00000000000000)
			{
				depth = 56 + bitIndex[((xorKey & 0xFF00000000000000)>>56)];
			}
			else
			{
				depth = 48 + bitIndex[((xorKey & 0x00FF000000000000)>>48)];
			}
		}
		else
		{
			if	(xorKey & 0x0000FF0000000000)
			{
				depth = 40 + bitIndex[((xorKey & 0x0000FF0000000000)>>40)];
			}
			else
			{
				depth = 32 + bitIndex[((xorKey & 0x000000FF00000000)>>32)];
			}
		}
	}
	else
#endif
	{
		if  (xorKey & 0x00000000FFFF0000)
		{
			if	(xorKey & 0x00000000FF000000)
			{
				depth = 24 + bitIndex[((xorKey & 0x00000000FF000000)>>24)];
			}
			else
			{
				depth = 16 + bitIndex[((xorKey & 0x0000000000FF0000)>>16)];
			}
		}
		else
		{
			if	(xorKey & 0x000000000000FF00)
			{
				depth = 8 + bitIndex[((xorKey & 0x0000000000000FF00)>>8)];
			}
			else
			{
				depth = bitIndex[xorKey & 0x00000000000000FF];
			}
		}
	}

    /* We have located the leftmost differing bit, indicated by the depth variable. So, we know what
     * bit index we are to insert the new entry at. There are two cases, being where the two keys
     * differ at a bit position that is not currently part of the bit testing, where they differ on a bit
     * that is currently being skipped in the indexed comparisons, and where they differ on a bit
     * that is merely lower down in the current bit search. If the bit index went bit 4, bit 2 and they differ
     * at bit 3, then we have the "skipped" bit case. But if that chain was Bit 4, Bit 2 and they differ at bit 1
     * then we have the easy bit <pun>.
     *
     * So, set up to descend the tree again, but this time looking for the insert point
     * according to whether we skip the bit that differs or not.
     */
    thisNode	= m_root;
    entNode	= m_root->get_leftN();

    /* Note the slight difference in the checks here to cover both cases
     */
    while (thisNode->get_bitNum() > entNode->get_bitNum() && entNode->get_bitNum() > depth)
    {
		/* Still descending the structure, next node becomes current.
		 */
		thisNode = entNode;

		if (key & bitMask[entNode->get_bitNum()])
		{
			/* Bit at the required index was 1, so traverse the right node from here
			 */
			entNode = entNode->get_rightN();
		}
		else
		{
			/* Bit at the required index was 0, so we traverse to the left
			 */
			entNode = entNode->get_leftN();
		}
    }

    /* We have located the correct insert point for this new key, so we need
     * to allocate our entry and insert it etc.
     */
    nextNode	= new IntTrieNodeType();

    /* Build a new entry block for the new node
     */
    newEnt = new TrieEntryType(data, NULL);

	/* Install it
     */
    nextNode->set_buckets(newEnt);
    nextNode->set_key(key);
    nextNode->set_bitNum( depth );

    /* Work out the right and left pointers for this new node, which involve
     * terminating with the current found node either right or left according
     * to whether the current index bit is 1 or 0
     */
    if (key & bitMask[depth])
    {
		nextNode->set_leftN(entNode);	    /* Terminates at previous position	*/
		nextNode->set_rightN(nextNode);	    /* Terminates with itself		*/
    }
    else
    {
		nextNode->set_rightN(entNode);	    /* Terminates at previous position	*/
		nextNode->set_leftN(nextNode);	    /* Terminates with itself		*/		
    }

    /* Finally, we need to change the pointers at the node we located
     * for inserting. If the key bit at its index is set then the right
     * pointer for that node becomes the newly created node, otherwise the left 
     * pointer does.
     */
    if (key & bitMask[thisNode->get_bitNum()] )
    {
		thisNode->set_rightN( nextNode );
    }
    else
    {
		thisNode->set_leftN(nextNode);
    }

    /* Et voila
     */
    m_count++;
    return  true;
}

template< class ImplTraits, class DataType >
IntTrieNode<ImplTraits, DataType>::IntTrieNode()
{
	m_bitNum = 0;
	m_key = 0;
	m_buckets = NULL;
	m_leftN = NULL;
	m_rightN = NULL;
}

template< class ImplTraits, class DataType >
IntTrieNode<ImplTraits, DataType>::~IntTrieNode()
{
	TrieEntryType*	thisEntry;
    TrieEntryType*	nextEntry;

    /* If this node has a left pointer that is not a back pointer
     * then recursively call to free this
     */
    if ( m_bitNum > m_leftN->get_bitNum())
    {
		/* We have a left node that needs descending, so do it.
		 */
		delete m_leftN;
    }

    /* The left nodes from here should now be dealt with, so 
     * we need to descend any right nodes that are not back pointers
     */
    if ( m_bitNum > m_rightN->get_bitNum() )
    {
		/* There are some right nodes to descend and deal with.
		 */
		delete m_rightN;
    }

    /* Now all the children are dealt with, we can destroy
     * this node too
     */
    thisEntry	= m_buckets;

    while (thisEntry != NULL)
    {
		nextEntry   = thisEntry->get_next();

		/* Now free the data for this bucket entry
		 */
		delete thisEntry;
		thisEntry = nextEntry;	    /* See if there are any more to free    */
    }

    /* The bucket entry is now gone, so we can free the memory for
     * the entry itself.
     */

    /* And that should be it for everything under this node and itself
     */
}

/**
 * Allocate and initialize a new ANTLR3 topological sorter, which can be
 * used to define edges that identify numerical node indexes that depend on other
 * numerical node indexes, which can then be sorted topologically such that
 * any node is sorted after all its dependent nodes.
 *
 * Use:
 *
 * /verbatim

  pANTLR3_TOPO topo;
  topo = antlr3NewTopo();

  if (topo == NULL) { out of memory }

  topo->addEdge(topo, 3, 0); // Node 3 depends on node 0
  topo->addEdge(topo, 0, 1); // Node - depends on node 1
  topo->sortVector(topo, myVector); // Sort the vector in place (node numbers are the vector entry numbers)

 * /verbatim
 */
template<class ImplTraits>
Topo<ImplTraits>::Topo()
{
    // Initialize variables
    //
    m_visited   = NULL;                 // Don't know how big it is yet
    m_limit     = 1;                    // No edges added yet
    m_edges     = NULL;                 // No edges added yet
    m_sorted    = NULL;                 // Nothing sorted at the start
    m_cycle     = NULL;                 // No cycles at the start
    m_cycleMark = 0;                    // No cycles at the start
    m_hasCycle  = false;         // No cycle at the start
}

// Topological sorter
//
template<class ImplTraits>
void Topo<ImplTraits>::addEdge(ANTLR_UINT32 edge, ANTLR_UINT32 dependency)
{
	ANTLR_UINT32   i;
    ANTLR_UINT32   maxEdge;
    BitsetType*  edgeDeps;

    if (edge>dependency)
    {
        maxEdge = edge;
    }
    else
    {
        maxEdge = dependency;
    }
    // We need to add an edge to says that the node indexed by 'edge' is
    // dependent on the node indexed by 'dependency'
    //

    // First see if we have enough room in the edges array to add the edge?
    //
    if ( m_edges == NULL)
    {
        // We don't have any edges yet, so create an array to hold them
        //
        m_edges = AllocPolicyType::alloc0(sizeof(BitsetType*) * (maxEdge + 1));

        // Set the limit to what we have now
        //
        m_limit = maxEdge + 1;
    }
    else if (m_limit <= maxEdge)
    {
        // WE have some edges but not enough
        //
        m_edges = AllocPolicyType::realloc(m_edges, sizeof(BitsetType*) * (maxEdge + 1));

        // Initialize the new bitmaps to ;indicate we have no edges defined yet
        //
        for (i = m_limit; i <= maxEdge; i++)
        {
            *((m_edges) + i) = NULL;
        }

        // Set the limit to what we have now
        //
        m_limit = maxEdge + 1;
    }

    // If the edge was flagged as depending on itself, then we just
    // do nothing as it means this routine was just called to add it
    // in to the list of nodes.
    //
    if  (edge == dependency)
    {
        return;
    }

    // Pick up the bit map for the requested edge
    //
    edgeDeps = *((m_edges) + edge);

    if  (edgeDeps == NULL)
    {
        // No edges are defined yet for this node
        //
        edgeDeps                = new BitsetType(0);
        *((m_edges) + edge) = edgeDeps;
    }

    // Set the bit in the bitmap that corresponds to the requested
    // dependency.
    //
    edgeDeps->add(dependency);

    // And we are all set
    //
    return;

}

/**
 * Given a starting node, descend its dependent nodes (ones that it has edges
 * to) until we find one without edges. Having found a node without edges, we have
 * discovered the bottom of a depth first search, which we can then ascend, adding
 * the nodes in order from the bottom, which gives us the dependency order.
 */
template<class ImplTraits>
void Topo<ImplTraits>::DFS(ANTLR_UINT32 node)
{
	BitsetType* edges;

    // Guard against a revisit and check for cycles
    //
    if  (m_hasCycle == true)
    {
        return; // We don't do anything else if we found a cycle
    }

    if  ( m_visited->isMember(node))
    {
        // Check to see if we found a cycle. To do this we search the
        // current cycle stack and see if we find this node already in the stack.
        //
        ANTLR_UINT32   i;

        for (i=0; i< m_cycleMark; i++)
        {
            if  ( m_cycle[i] == node)
            {
                // Stop! We found a cycle in the input, so rejig the cycle
                // stack so that it only contains the cycle and set the cycle flag
                // which will tell the caller what happened
                //
                ANTLR_UINT32 l;

                for (l = i; l < m_cycleMark; l++)
                {
                    m_cycle[l - i] = m_cycle[l];    // Move to zero base in the cycle list
                }

                // Recalculate the limit
                //
                m_cycleMark -= i;

                // Signal disaster
                //
                m_hasCycle = true;
            }
        }
        return;
    }

    // So far, no cycles have been found and we have not visited this node yet,
    // so this node needs to go into the cycle stack before we continue
    // then we will take it out of the stack once we have descended all its
    // dependencies.
    //
    m_cycle[m_cycleMark++] = node;

    // First flag that we have visited this node
    //
    m_visited->add(node);

    // Now, if this node has edges, then we want to ensure we visit
    // them all before we drop through and add this node into the sorted
    // list.
    //
    edges = *((m_edges) + node);
    if  (edges != NULL)
    {
        // We have some edges, so visit each of the edge nodes
        // that have not already been visited.
        //
        ANTLR_UINT32   numBits;	    // How many bits are in the set
        ANTLR_UINT32   i;
        ANTLR_UINT32   range;

        numBits = edges->numBits();
        range   = edges->size();   // Number of set bits

        // Stop if we exahust the bit list or have checked the
        // number of edges that this node refers to (so we don't
        // check bits at the end that cannot possibly be set).
        //
        for (i=0; i<= numBits && range > 0; i++)
        {
            if  (edges->isMember(i))
            {
                range--;        // About to check another one

                // Found an edge, make sure we visit and descend it
                //
                this->DFS(i);
            }
        }
    }

    // At this point we will have visited all the dependencies
    // of this node and they will be ordered (even if there are cycles)
    // So we just add the node into the sorted list at the
    // current index position.
    //
    m_sorted[m_limit++] = node;

    // Remove this node from the cycle list if we have not detected a cycle
    //
    if  (m_hasCycle == false)
    {
        m_cycleMark--;
    }

    return;
}

template<class ImplTraits>
ANTLR_UINT32*  Topo<ImplTraits>::sortToArray()
{
	ANTLR_UINT32 v;
    ANTLR_UINT32 oldLimit;

    // Guard against being called with no edges defined
    //
    if  (m_edges == NULL)
    {
        return 0;
    }
    // First we need a vector to populate with enough
    // entries to accomodate the sorted list and another to accomodate
    // the maximum cycle we could detect which is all nodes such as 0->1->2->3->0
    //
    m_sorted    = AllocPolicyType::alloc( m_limit * sizeof(ANTLR_UINT32) );
    m_cycle     = AllocPolicyType::alloc( m_limit * sizeof(ANTLR_UINT32));

    // Next we need an empty bitset to show whether we have visited a node
    // or not. This is the bit that gives us linear time of course as we are essentially
    // dropping through the nodes in depth first order and when we get to a node that
    // has no edges, we pop back up the stack adding the nodes we traversed in reverse
    // order.
    //
    m_visited   = new BitsetType(0);

    // Now traverse the nodes as if we were just going left to right, but
    // then descend each node unless it has already been visited.
    //
    oldLimit    = m_limit;     // Number of nodes to traverse linearly
    m_limit = 0;               // Next entry in the sorted table

    for (v = 0; v < oldLimit; v++)
    {
        // If we did not already visit this node, then descend it until we
        // get a node without edges or arrive at a node we have already visited.
        //
        if  (m_visited->isMember(v) == false)
        {
            // We have not visited this one so descend it
            //
            this->DFS(v);
        }

        // Break the loop if we detect a cycle as we have no need to go any
        // further
        //
        if  (m_hasCycle == true)
        {
            break;
        }
    }

    // Reset the limit to the number we recorded as if we hit a
    // cycle, then limit will have stopped at the node where we
    // discovered the cycle, but in order to free the edge bitmaps
    // we need to know how many we may have allocated and traverse them all.
    //
    m_limit = oldLimit;

    // Having traversed all the nodes we were given, we
    // are guaranteed to have ordered all the nodes or detected a
    // cycle.
    //
    return m_sorted;
}

template<class ImplTraits>
	template<typename DataType>
void   Topo<ImplTraits>::sortVector(  typename ImplTraits::template VectorType<DataType>& v )
{
    // To sort a vector, we first perform the
    // sort to an array, then use the results to reorder the vector
    // we are given. This is just a convenience routine that allows you to
    // sort the children of a tree node into topological order before or
    // during an AST walk. This can be useful for optimizations that require
    // dag reorders and also when the input stream defines thigns that are
    // interdependent and you want to walk the list of the generated trees
    // for those things in topological order so you can ignore the interdependencies
    // at that point.
    //
    ANTLR_UINT32 i;

    // Used as a lookup index to find the current location in the vector of
    // the vector entry that was originally at position [0], [1], [2] etc
    //
    ANTLR_UINT32*  vIndex;

    // Sort into an array, then we can use the array that is
    // stored in the topo
    //
    if  (this->sortToArray() == 0)
    {
        return;     // There were no edges
    }

    if  (m_hasCycle == true)
    {
        return;  // Do nothing if we detected a cycle
    }

    // Ensure that the vector we are sorting is at least as big as the
    // the input sequence we were adsked to sort. It does not matter if it is
    // bigger as thaat probably just means that nodes numbered higher than the
    // limit had no dependencies and so can be left alone.
    //
    if  (m_limit > v.size() )
    {
        // We can only sort the entries that we have dude! The caller is
        // responsible for ensuring the vector is the correct one and is the
        // correct size etc.
        //
        m_limit = v.size();
    }
    // We need to know the locations of each of the entries
    // in the vector as we don't want to duplicate them in a new vector. We
    // just use an indirection table to get the vector entry for a particular sequence
    // acording to where we moved it last. Then we can just swap vector entries until
    // we are done :-)
    //
    vIndex = AllocPolicyType::alloc(m_limit * sizeof(ANTLR_UINT32));

    // Start index, each vector entry is located where you think it is
    //
    for (i = 0; i < m_limit; i++)
    {
        vIndex[i] = i;
    }

    // Now we traverse the sorted array and moved the entries of
    // the vector around according to the sort order and the indirection
    // table we just created. The index telsl us where in the vector the
    // original element entry n is now located via vIndex[n].
    //
    for (i=0; i < m_limit; i++)
    {
        ANTLR_UINT32   ind;

        // If the vector entry at i is already the one that it
        // should be, then we skip moving it of course.
        //
        if  (vIndex[m_sorted[i]] == i)
        {
            continue;
        }

        // The vector entry at i, should be replaced with the
        // vector entry indicated by topo->sorted[i]. The vector entry
        // at topo->sorted[i] may have already been swapped out though, so we
        // find where it is now and move it from there to i.
        //
        ind     = vIndex[m_sorted[i]];
		std::swap( v[i], v[ind] );

        // Update our index. The element at i is now the one we wanted
        // to be sorted here and the element we swapped out is now the
        // element that was at i just before we swapped it. If you are lost now
        // don't worry about it, we are just reindexing on the fly is all.
        //
        vIndex[m_sorted[i]] = i;
        vIndex[i] = ind;
    }

    // Having traversed all the entries, we have sorted the vector in place.
    //
    AllocPolicyType::free(vIndex);
    return;
}

template<class ImplTraits>
Topo<ImplTraits>::~Topo()
{
    ANTLR_UINT32   i;

    // Free the result vector
    //
    if  (m_sorted != NULL)
    {
        AllocPolicyType::free(m_sorted);
    }

    // Free the visited map
    //
    if  (m_visited != NULL)
    {
		delete m_visited;
    }

    // Free any edgemaps
    //
    if  (m_edges != NULL)
    {
        Bitset<AllocPolicyType>* edgeList;

        for (i=0; i<m_limit; i++)
        {
            edgeList = *((m_edges) + i);
            if  (edgeList != NULL)
            {
				delete edgeList;
            }
        }

        AllocPolicyType::free( m_edges );
    }
    m_edges = NULL;
    
    // Free any cycle map
    //
    if  (m_cycle != NULL)
    {
        AllocPolicyType::free(m_cycle);
    }
}


ANTLR_END_NAMESPACE()
