/*
 * RegExp.h
 *
 *  Created on: Apr 10, 2013
 *      Author: Martin Zak
 */

#ifndef REG_EXP_H_
#define REG_EXP_H_

#include <alib/string>
#include <alib/vector>
#include <alib/type_traits>

#include <common/DefaultSymbolType.h>

#include "unbounded/UnboundedRegExpSymbol.h"
#include "unbounded/UnboundedRegExpEmpty.h"
#include "unbounded/UnboundedRegExpConcatenation.h"

#include "unbounded/UnboundedRegExp.h"
#include "unbounded/UnboundedRegExpStructure.h"

#include <string/LinearString.h>

namespace regexp {

/**
 * Wrapper around automata.
 */
class RegExp;

template < class T >
using SymbolTypeOfRegexp = typename std::decay < decltype (std::declval<T>().getAlphabet()) >::type::value_type;

regexp::UnboundedRegExp < char > regexpFrom ( const std::string & string );

regexp::UnboundedRegExp < char > regexpFrom ( const char * string );

template < class SymbolType >
regexp::UnboundedRegExp < SymbolType > regexpFrom ( ext::vector < SymbolType > string ) {
	regexp::UnboundedRegExpConcatenation < SymbolType > con;

	for ( auto & symbol : string )
		con.appendElement ( regexp::UnboundedRegExpSymbol < SymbolType > ( symbol ) );

	return regexp::UnboundedRegExp < SymbolType > ( regexp::UnboundedRegExpStructure < SymbolType > ( std::move ( con ) ) );
}

template < class SymbolType >
regexp::UnboundedRegExp < SymbolType > regexpFrom ( string::LinearString < SymbolType > string ) {
	return regexpFrom ( string.getContent ( ) );
}

template < class SymbolType >
regexp::UnboundedRegExp < SymbolType > regexpFrom ( const SymbolType & symbol ) {
	return regexp::UnboundedRegExp < SymbolType > ( regexp::UnboundedRegExpStructure < SymbolType > ( regexp::UnboundedRegExpSymbol < SymbolType > ( symbol ) ) );
}

template < class SymbolType = DefaultSymbolType >
regexp::UnboundedRegExp < SymbolType > regexpFrom ( );

} /* namespace regexp */

#endif /* REG_EXP_H_ */
