/*
 * SymbolOrEpsilon.h
 *
 * Created on: Sep 27, 2017
 * Author: Jan Travnicek
 */

#ifndef _XML_SYMBOL_OR_EPSILON_H_
#define _XML_SYMBOL_OR_EPSILON_H_

#include <common/symbol_or_epsilon.hpp>
#include <core/xmlApi.hpp>

namespace core {

template < class T >
struct xmlApi < common::symbol_or_epsilon < T > > {
	static common::symbol_or_epsilon < T > parse ( ext::deque < sax::Token >::iterator & input );
	static bool first ( const ext::deque < sax::Token >::const_iterator & input );
	static std::string xmlTagName ( );
	static void compose ( ext::deque < sax::Token > & output, const common::symbol_or_epsilon < T > & input );
};

template < typename T >
common::symbol_or_epsilon < T > xmlApi < common::symbol_or_epsilon < T > >::parse ( ext::deque < sax::Token >::iterator & input ) {
	if ( sax::FromXMLParserHelper::isToken ( input, sax::Token::TokenType::START_ELEMENT, "epsilon" ) ) {
		++input;
		sax::FromXMLParserHelper::popToken ( input, sax::Token::TokenType::END_ELEMENT, "epsilon" );
		return common::symbol_or_epsilon < T > ( );
	} else {
		return common::symbol_or_epsilon < T > ( core::xmlApi < T >::parse ( input ) );
	}
}

template < typename T >
bool xmlApi < common::symbol_or_epsilon < T > >::first ( const ext::deque < sax::Token >::const_iterator & input ) {
	return sax::FromXMLParserHelper::isToken ( input, sax::Token::TokenType::START_ELEMENT, "epsilon" ) || xmlApi < T >::first ( input );
}

template < typename T >
std::string xmlApi < common::symbol_or_epsilon < T > >::xmlTagName ( ) {
	throw exception::CommonException ( "Symbol of epsilon should not provide xmlTagName call." );
}

template < typename T >
void xmlApi < common::symbol_or_epsilon < T > >::compose ( ext::deque < sax::Token > & output, const common::symbol_or_epsilon < T > & input ) {
	if ( input.is_epsilon ( ) ) {
		output.emplace_back("epsilon", sax::Token::TokenType::START_ELEMENT);
		output.emplace_back("epsilon", sax::Token::TokenType::END_ELEMENT);
	} else {
		core::xmlApi<T>::compose(output, input.getSymbol ( ) );
	}
}

} /* namespace core */

#endif /* _XML_SYMBOL_OR_EPSILON_H_ */
