/*
 * RegExpAlternate.h
 *
 *  Created on: 17. 10. 2014
 *	  Author: Jan Travnicek
 */

#pragma once

#include <regexp/formal/FormalRegExp.h>
#include <regexp/unbounded/UnboundedRegExp.h>

#include <regexp/formal/FormalRegExpAlternation.h>
#include <regexp/unbounded/UnboundedRegExpAlternation.h>

namespace regexp {

namespace transform {

/**
 * Implements alternation of two regular expressions.
 *
 */
class RegExpAlternate {
public:
	/**
	 * Implements alternation of two regular expressions.
	 *
	 * \tparam SymbolType the type of symbols in the regular expression
	 *
	 * \param first the first regexp to alternate
	 * \param second the second regexp to alternate
	 *
	 * \return regexp describing @p first + @p second
	 */
	template < class SymbolType >
	static regexp::FormalRegExp < SymbolType > alternate(const regexp::FormalRegExp < SymbolType > & first, const regexp::FormalRegExp < SymbolType > & second);

	/**
	 * \override
	 */
	template < class SymbolType >
	static regexp::FormalRegExpStructure < SymbolType > alternate(const regexp::FormalRegExpStructure < SymbolType > & first, const regexp::FormalRegExpStructure < SymbolType > & second);

	/**
	 * \override
	 */
	template < class SymbolType >
	static regexp::UnboundedRegExp < SymbolType > alternate(const regexp::UnboundedRegExp < SymbolType > & first, const regexp::UnboundedRegExp < SymbolType > & second);

	/**
	 * \override
	 */
	template < class SymbolType >
	static regexp::UnboundedRegExpStructure < SymbolType > alternate(const regexp::UnboundedRegExpStructure < SymbolType > & first, const regexp::UnboundedRegExpStructure < SymbolType > & second);
};

template < class SymbolType >
regexp::FormalRegExp < SymbolType > RegExpAlternate::alternate(const regexp::FormalRegExp < SymbolType > & first, const regexp::FormalRegExp < SymbolType > & second) {
	return regexp::FormalRegExp < SymbolType > (RegExpAlternate::alternate(first.getRegExp(), second.getRegExp()));
}

template < class SymbolType >
regexp::FormalRegExpStructure < SymbolType > RegExpAlternate::alternate(const regexp::FormalRegExpStructure < SymbolType > & first, const regexp::FormalRegExpStructure < SymbolType > & second) {
	return regexp::FormalRegExpStructure < SymbolType > (regexp::FormalRegExpAlternation < SymbolType > (first.getStructure(), second.getStructure()));
}

template < class SymbolType >
regexp::UnboundedRegExp < SymbolType > RegExpAlternate::alternate(const regexp::UnboundedRegExp < SymbolType > & first, const regexp::UnboundedRegExp < SymbolType > & second) {
	return regexp::UnboundedRegExp < SymbolType > (RegExpAlternate::alternate(first.getRegExp(), second.getRegExp()));
}

template < class SymbolType >
regexp::UnboundedRegExpStructure < SymbolType > RegExpAlternate::alternate(const regexp::UnboundedRegExpStructure < SymbolType > & first, const regexp::UnboundedRegExpStructure < SymbolType > & second) {
	regexp::UnboundedRegExpAlternation < SymbolType > con;
	con.appendElement(first.getStructure());
	con.appendElement(second.getStructure());
	return regexp::UnboundedRegExpStructure < SymbolType > (con);
}

} /* namespace transform */

} /* namespace regexp */

