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

#ifndef REG_EXP_CONCATENATE_H_
#define REG_EXP_CONCATENATE_H_

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

#include "regexp/formal/FormalRegExpConcatenation.h"
#include "regexp/unbounded/UnboundedRegExpConcatenation.h"

namespace regexp {

namespace transform {

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

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

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

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

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

template < class SymbolType >
regexp::FormalRegExpStructure < SymbolType > RegExpConcatenate::concatenate(const regexp::FormalRegExpStructure < SymbolType > & first, const regexp::FormalRegExpStructure < SymbolType > & second) {
	return regexp::FormalRegExpStructure < SymbolType > (regexp::FormalRegExpConcatenation < SymbolType > (first.getStructure(), second.getStructure()));
}

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

template < class SymbolType >
regexp::UnboundedRegExpStructure < SymbolType > RegExpConcatenate::concatenate(const regexp::UnboundedRegExpStructure < SymbolType > & first, const regexp::UnboundedRegExpStructure < SymbolType > & second) {
	regexp::UnboundedRegExpConcatenation < SymbolType > con;
	con.appendElement(first.getStructure());
	con.appendElement(second.getStructure());
	return regexp::UnboundedRegExpStructure < SymbolType > (con);
}

} /* namespace transform */

} /* namespace regexp */

#endif /* REG_EXP_CONCATENATE_H_ */
