/*
 * ToRegExpStateElimination.h
 *
 *  Created on: 9. 2. 2014
 *	  Author: Tomas Pecka
 */

#ifndef TO_REG_EXP_STATE_ELIMINATION_H_
#define TO_REG_EXP_STATE_ELIMINATION_H_

#include <regexp/RegExp.h>

#include <automaton/Automaton.h>
#include <automaton/FSM/DFA.h>
#include <automaton/FSM/NFA.h>
#include <automaton/FSM/MultiInitialStateNFA.h>
#include <automaton/FSM/EpsilonNFA.h>
#include <automaton/FSM/ExtendedNFA.h>

namespace automaton {

namespace convert {

/**
 * Converts FSM to RE using State Elimination algorithm.
 * Source: Melichar 2.118
 */
class ToRegExpStateElimination : public automaton::VisitableConstFSMBase {
public:
	ToRegExpStateElimination() {}

	/**
	 * Performs conversion.
	 * @param automaton automaton to convert
	 * @return regular expression equivalent to source NFA.
	 */
	static regexp::RegExp convert(const automaton::Automaton& automaton);

	template<class T>
	static regexp::RegExp convert(const T& automaton);

private:
	using automaton::VisitableConstFSMBase::Visit;

	void Visit(void*, const automaton::EpsilonNFA& automaton) const;
	void Visit(void*, const automaton::MultiInitialStateNFA& automaton) const;
	void Visit(void*, const automaton::NFA& automaton) const;
	void Visit(void*, const automaton::DFA& automaton) const;
	void Visit(void*, const automaton::ExtendedNFA& automaton) const;
	void Visit(void*, const automaton::CompactNFA& automaton) const;

	static void extendExtendedNFA(automaton::ExtendedNFA& automaton);

	static const regexp::RegExp transition(const automaton::ExtendedNFA& automaton, const automaton::State& from, const automaton::State& to);

	static automaton::ExtendedNFA eliminateState(const automaton::ExtendedNFA& extendedAutomaton, const automaton::State& state);

	static const ToRegExpStateElimination TO_REG_EXP_STATE_ELIMINATION;
};

} /* namespace convert */

} /* namespace automaton */

#endif /* TO_REG_EXP_STATE_ELIMINATION_H_ */