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

#ifndef _STRING_UNRANKED_TREE_H_
#define _STRING_UNRANKED_TREE_H_

#include <tree/unranked/UnrankedTree.h>
#include <core/stringApi.hpp>

#include <tree/TreeFromStringLexer.h>

#include <tree/string/common/TreeFromStringParserCommon.h>
#include <tree/string/common/TreeToStringComposerCommon.h>

namespace core {

template<class SymbolType >
struct stringApi < tree::UnrankedTree < SymbolType > > {
	static tree::UnrankedTree < SymbolType > parse ( std::istream & input );
	static bool first ( std::istream & input );
	static void compose ( std::ostream & output, const tree::UnrankedTree < SymbolType > & tree );
};

template<class SymbolType >
tree::UnrankedTree < SymbolType > stringApi < tree::UnrankedTree < SymbolType > >::parse ( std::istream & input ) {
	tree::TreeFromStringLexer::Token token = tree::TreeFromStringLexer::next ( input );
	if ( token.type != tree::TreeFromStringLexer::TokenType::UNRANKED_TREE )
		throw exception::CommonException ( "Unrecognised UNRANKED_TREE token." );

	ext::set < SymbolType > nonlinearVariables;
	bool isPattern = false;

	ext::tree < SymbolType > content = tree::TreeFromStringParserCommon::parseUnrankedContent < SymbolType > ( input, isPattern, nonlinearVariables );
	if ( isPattern || !nonlinearVariables.empty ( ) )
		throw exception::CommonException ( "Invalid input" );

	return tree::UnrankedTree < SymbolType > ( content );
}

template<class SymbolType >
bool stringApi < tree::UnrankedTree < SymbolType > >::first ( std::istream & input ) {
	tree::TreeFromStringLexer::Token token = tree::TreeFromStringLexer::next ( input );
	bool res = token.type == tree::TreeFromStringLexer::TokenType::UNRANKED_TREE;
	tree::TreeFromStringLexer::putback ( input, token );
	return res;
}

template<class SymbolType >
void stringApi < tree::UnrankedTree < SymbolType > >::compose ( std::ostream & output, const tree::UnrankedTree < SymbolType > & tree ) {
	output << "UNRANKED_TREE ";
	tree::TreeToStringComposerCommon::compose ( output, tree.getContent ( ) );
}

} /* namespace core */

#endif /* _STRING_UNRANKED_TREE_H_ */
