def crawl(alphabet, initial, final, follow):
	'''
		Given the above conditions and instructions, crawl a new unknown FSM,
		mapping its states, final states and transitions. Return the new FSM.
		This is a pretty powerful procedure which could potentially go on
		forever if you supply an evil version of follow().
	'''

	states = [initial]
	finals = set()
	map = {}

	# iterate over a growing list
	i = 0
	while i < len(states):
		state = states[i]

		# add to finals
		if final(state):
			finals.add(i)

		# compute map for this state
		map[i] = {}
		for symbol in sorted(alphabet, key=key):
			try:
				next = follow(state, symbol)

				try:
					j = states.index(next)
				except ValueError:
					j = len(states)
					states.append(next)

			except OblivionError:
				# Reached an oblivion state. Don't list it.
				continue

			map[i][symbol] = j

		i += 1

	return fsm(
		alphabet = alphabet,
		states   = range(len(states)),
		initial  = 0,
		finals   = finals,
		map      = map,
	)