private HashSet<Symbol> epsilonClosure(NFAState s)
	{
		// This is a memoized method. If the closure of this state has been encountered before,
		// return the previously computed closure.
		if(memoizedEpsClosures.containsKey(s))
		{
			return memoizedEpsClosures.get(s);
		}
		// A FIFO queue to perform a nondeterministic breadth-first search
		// of the NFA appertaining unto s.
		LinkedList<NFAState> stateQueue = new LinkedList<NFAState>();
		HashSet<Symbol> rv = new HashSet<Symbol>();
		// Put s in the BFS queue.
		stateQueue.offer(s);
		// For each NFA state encountered:
		while(!stateQueue.isEmpty())
		{
			NFAState front = stateQueue.poll();
			// Add all identifying symbols to the closure.
			rv.addAll(front.getIdentifier());
			// For every state reachable by epsilon transition from the current,
			// if it is not already a subset of the closure, put it in the queue.
			for(NFAState n : front.getTransitions(new CharacterRange(NFAState.EmptyChar)))
			{
				if(!rv.containsAll(n.getIdentifier())) stateQueue.offer(n);
			}
		}
		// DEBUG-X-BEGIN
		// System.err.println("Epsilon-closure of " + s + ": " + rv);
		// DEBUG-X-END
		// Put the memoized closure in the memory.
		memoizedEpsClosures.put(s,rv);
		return rv;
	}